<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type"
    content="text/html; charset=us-ascii" />
  <title>Dynamic memory allocation for over-aligned data</title>
  <style type="text/css">
    .decl {
      margin-left: -2em;
    }

    .right {
      float: right;
    }

    .new {
      border-color: red;
      border-style: dashed;
      border-width: thin;
    }

    p.new, div.new {
      padding-left: 1em;
      padding-right: 1em;
    }

    .ed {
      font-family: sans-serif;
    }

    span.ed {
      background-color: #FF9;
    }

      span.ed:before {
        content: "[";
      }

      span.ed:after {
        content: "]";
      }

    p.numbered {
      text-indent: -3em;
      margin-left: 3em;
      counter-increment: p;
    }

      p.numbered:before {
        content: counter(p) "\A0\A0\A0";
      }

    h4 {
      counter-reset: p;
    }

    del {
      background-color: #FCC;
    }

    ins {
      background-color: #CFC;
    }

    pre, ul {
      background-color: inherit;
    }

    body {
      font-family: sans-serif;
    }

    blockquote {
      font-family: serif;
    }
  </style>
</head>
<body>
  <table border="1" class="right">
    <tbody>
      <tr>
	<th>Doc. No.:</th>
	<td>P0035R4</td>
      </tr>
      <tr>
	<th>Date:</th>
	<td>2016-06-21</td>
      </tr>
      <tr>
	<th>Reply to:</th>
	<td>Clark Nelson</td>
      </tr>
      <tr>
	<th>Phone:</th>
	<td>+1-503-712-8433</td>
      </tr>
      <tr>
	<th>Email:</th>
	<td><a href="mailto:clark.nelson@intel.com">clark.nelson@intel.com</a></td>
      </tr>
      <tr>
	<th>Audience:</th>
	<td>Core, Library Evolution</td>
      </tr>
    </tbody>
  </table>
  <h1>Dynamic memory allocation for over-aligned data</h1>
  <h2>Problem statement</h2>
  <p>To codify widespread existing practice,
    C++11 added the ability to specify increased alignment
    (a.k.a. over-alignment) for class types.
    Unfortunately (but also consistently with existing practice),
    C++11 did not specify any mechanism
    by which over-aligned data can be dynamically allocated correctly
    (i.e. respecting the alignment of the data).
    For example:</p>
  <pre>class alignas(16) float4 {
	float f[4];
};
float4 *p = new float4[1000];</pre>
  <p>In this example,
    not only is an implementation of C++ <strong>not</strong> required
    to allocate properly-aligned memory for the array,
    for practical purposes it is very nearly required
    to do the allocation incorrectly.
    In any event,
    it is certainly required to perform the allocation by a process
    that does <strong>not</strong> take the specified alignment
    value into account.</p>
  <p>This represents a hole in the support for alignment in the language,
    which really needs to be filled.</p>
  <h2>History</h2>
  <p class="new">Significant changes in this revision
    relative to P0035R3,
    including all changes in the proposed wording,
    are enclosed in boxes.</p>
  <p>Intel has released a compiler
      that largely implements the language changes discussed herein,
      except that, to guarantee backward compatibility,
      the additional overloads are declared in a new header
      (<code>&lt;aligned_new&gt;</code>),
      instead of being predeclared or
      declared in <code>&lt;new&gt;</code>.</p>
  <p>To date,
      there has not yet been enough experience with the implementation
      to prove its viability.
      Nevertheless, it seems appropriate
      to get this issue back on the committee's radar,
      so that a decision can be made about it
      for the C++17 time frame.</p>
  <h2>Acknowledgements</h2>
  <p>Pablo Halpern has provided me with much valuable feedback
      and assistance.</p>
  <h2>Design considerations</h2>
  <h3>Backward compatibility</h3>
  <p>One of the first questions that needs to be settled
    about the future direction is
    the degree to which backward compatibility with C++11/14
    needs to be maintained.
    On the one hand, in an ideal world, for an example like the one above,
    it would be obvious that the specified alignment
    should be honored.</p>
  <p>On the other hand,
    there's no way to achieve that ideal
    without at least potentially changing the behavior
    of some programs conforming to an earlier standard.
    For example, a program might asssume control of dynamic allocation
    through the use of class-specific <code>operator new</code>
    and <code>operator delete</code> functions,
    or by replacing the global functions.
    These functions don't take any alignment argument.
    If a different function is used instead,
    which is somehow passed an alignment value,
    some degree of backward compatibility is lost.</p>
  <p>When backward compatibility
    and the ideal future direction are in conflict,
    which should take precedence, and to what degree?</p>
  <p>If perfect backward compatibility were required,
    one way to ensure that might be to require that a new header
    &ndash; say <code>&lt;aligned_new&gt;</code> &ndash;
    be included in order to get new dynamic allocation
    for over-aligned types.
    But that would sacrifice convenience and/or correctness;
    using <code>alignas</code> by itself would presumably never be enough
    to get correctly aligned dynamic allocation.</p>
  <p>Another obvious position to take
    would be that backward compatibility with C++98,
    which had no alignment specifier, needs to be complete.
    This might suggest that dynamic allocation should differ
    between types involving alignment specifiers
    and types that don't &ndash;
    which some might consider to be an unfortunate complication.</p>
  <p>In C++11/14, when an over-aligned class type
    has its own dynamic memory allocation functions,
    it would be reasonable to hope
    that those functions already do the right thing
    with respect to alignment, and dangerous to make any change.
    However, the only way over-alignment could be accommodated
    by global allocation and deallocation functions
    would be to replace them with functions
    that always provide the strictest alignment
    used by any type in the program.
    It may be reasonable to assume
    that very few programs go to that length,
    instead of using class-specific allocation/deallocation.</p>
  <p>Therefore, it may be acceptable to abandon backward compatibility
    with C++14 with respect to calling a global allocation function
    for dynamic allocation of an over-aligned type.
    But if so, that may well be the only acceptable case.</p>
  <h3>Passing the alignment value</h3>
  <p>To minimize the possibility of conflict
    with existing placement allocation functions,
    it might be advisable to invent a new standard enumeration type
    to use for alignment parameters; for example:</p>
  <pre>namespace std {
	enum class align_val_t: size_t;
};
void *operator new(std::size_t, std::align_val_t);	// new overload</pre>
  <p>It's not clear that this type would need
    any named constants of its own;
    it just needs to be able to represent alignment values,
    which are associated with type <code>size_t</code>.
    It should perhaps nevertheless be a scoped enumeration,
    to prevent the possibility that a value of that type
    would inadvertently be converted to some integer type,
    and match an existing placement allocation function.</p>
  <p>If an allocation function that takes an alignment value is available,
    it should be used, for the sake of generality;
    but if no such function is available,
    a function that doesn't take one should be used,
    for backward compatibility.
    This suggests a new rule for new-expressions:
    attempting to find an allocation function in two phases,
    with two different sets of arguments.
    <!--But Pablo Halpern suggested a different possibility,
	which wouldn't require a special meta-overload-resolution rule:-->
  </p>
  <!--
    <pre>namespace std {
	class aligned_size {
		size_t size, alignment;
	public:
		aligned_size(size_t size, size_t alignment);
		operator size_t();	// returns the size
	};
};
void *operator new(std::aligned_size);	// new overload</pre>
    <p>If for <code>new T</code> the compiler synthesized a call
	to <code>operator new(aligned_size(sizeof(T), alignof(T))</code>,
	the existing overload resolution rules would prefer a function
	with an <code>aligned_size</code> parameter,
	but would accept a function
	with a <code>size_t</code> parameter instead.</p>
    <p>The advantage of this approach
	is that no new language rule related to overload resolution
	would be needed.
	One disadvantage would be that it would be necessary to relax
	the current restriction that the first parameter
	of an allocation function have type <code>size_t</code>;
	it's not clear exactly what (if anything) should then be disallowed.
	Another disadvantage is that there would be
	a new language-support component of the library,
	on which the compiler would depend for correctness.
	The standard might not need to say anything about this,
	but for backward compatibility compilers might need to continue
	to use the old method
	if <code>std::aligned_size</code> is not defined.</p>
    <p>(It could be argued that the above <code>align_val_t</code> type
	would also imply a dependency by the compiler on the library,
	but that would actually involve far fewer necessary assumptions
	by the compiler.)</p>
    -->
  <h3>Class-specific allocation and deallocation</h3>
  <p>It should be kept in mind that,
    under the current language rules,
    any class-specific allocation functions effectively hide
    all global allocation functions,
    including the ones in the standard library.
    For example, the following is invalid:</p>
  <pre>#include &lt;new&gt;
class X {
	void *operator new(size_t);
	// no operator new(size_t, std::nothrow_t&amp;)
	void operator delete(void *);
};
X *p1 = new X;		// uses X::operator new(size_t)
X *p2 = new(nothrow) X;	// error
// ::operator new(size_t, std::nothrow_t&amp;) is not considered</pre>
  <p>It is possible to imagine adjusting the rules
    to enable finding an alignment-aware allocation function more often,
    but that would also make it more likely
    that some programmers would write programs believing
    &ndash; incorrectly &ndash;
    that they have taken over complete control
    of the way that their class is dynamically allocated.</p>
  <h3>Unified vs. distinct arenas</h3>
  <p>What implementation techniques should the standard allow
    for allocation and deallocation of aligned memory?</p>
  <p>In POSIX, there is a function named <code>posix_memalign</code>
    that can allocate over-aligned memory;
    <code>free</code> is used to free the blocks it allocates.</p>
  <p>On Windows, on the other hand, of course <code>malloc</code>,
    <code>realloc</code> and <code>free</code> are supported
    for default-aligned memory.
    In addition, for over-aligned memory, there are functions named
    <code>_aligned_malloc</code>, <code>_aligned_realloc</code>,
    and <code>_aligned_free</code>.
    Memory that's allocated by <code>_aligned_malloc</code>
    must be freed by <code>_aligned_free</code>,
    and memory that's allocated by <code>malloc</code>
    must be freed by <code>free</code>.
    So logically, there are two disjoint, non-interoperable memory arenas;
    the program has to know to which arena a block belongs
    (i.e. how it was allocated)
    in order to be able to free it.</p>
  <p>This is almost certain to be true of any implementation
    where over-aligned memory allocation is layered
    on top of &ldquo;plain old&rdquo; default-aligned memory allocation.
    There are probably many such implementations,
    and they're not likely to go away soon.</p>
  <p>In an environment where information about the method used
    to allocate a block of memory can be lost,
    having distinct arenas (i.e. distinct deallocation functions)
    could be inconvenient.
    A program whose operation depends on the assumption
    that <code>operator new</code> is equivalent to <code>malloc</code>
    is effectively an environment where information about the method
    used to allocate a block of memory is lost.</p>
  <p>But in a well-written, portable C++ program,
    at the point where memory is deallocated,
    the type of the object being deleted &ndash;
    and therefore whether it is over-aligned &ndash; is known.
    This knowledge could, and probably should,
    be used to support layered implementations
    of over-aligned memory allocation.</p>
  <p>This implies that, just as a new-expression for an over-aligned type
    should look for an alignment-aware allocation function,
    so should a delete-expression for a pointer to an over-aligned type
    look for an alignment-aware deallocation function.
    Presumably this would be done by selecting a deallocation function
    to which the alignment value can be passed,
    even though probably very few implementations
    will actually have any use for that value.</p>
  <h3>Nitty-gritty</h3>
  <p>For exactly what classes should the allocation method change?
      Plausible answers include:</p>
  <ol>
    <li>Those affected by an <code>alignas</code>
      that actually specifies over-alignment.</li>
    <li>Those affected by an explicit <code>alignas</code>,
	even if the alignment value is basic (i.e. small).</li>
  </ol>
  <p>The first answer seems to be right from a pragmatic perspective,
      but one consequence is that the behavior of a program might depend
      (in a new way)
      on an implementation-defined parameter.
      But if the only difference between alignment-aware
      and alignment-unaware
      allocation/deallocation functions
      is the actual allocation mechanism
      (i.e., in a well-designed program),
      this should not be a problem.
      It's rather like the implementation's license
      to elide certain copies,
      which implies that a copy constructor
      had really better just make a copy.</p>
  <p>The below WD changes use the first answer,
      through use of &ldquo;over-aligned&rdquo;.
      The Intel implementation uses the first answer by default,
      but has a command-line option to select the second answer,
      for the sake of experimentation.</p>
  <p>Also, it should be noted that the over-alignment threshold
      used by the Intel implementation doesn't exactly match
      the standard's definition of basic alignment.
      The threshold used is actually the alignment
      observed to be guaranteed
      by the implementation of <code>malloc</code>
    for the target environment.
      (In all of the environments tested,
      this turned out to be twice the size of a pointer.)</p>
  <p>Assuming the existence of a variety of allocation functions,
      which one should be used for an over-aligned allocation?
      I believe the answer should be
      the first one from the following list that is known to exist:</p>
  <ol>
    <li>class-specific and alignment-aware</li>
    <li>class-specific and alignment-unaware</li>
    <li>global and alignment-aware</li>
    <li>[global and alignment-unaware]</li>
  </ol>
  <p>It makes sense for a class-specific,
      alignment-unaware allocation function to be preferred
      over one that is global and alignment-aware,
      because there are many cases
      where a class-specific allocation function has enough information,
      even without an explicit parameter,
      to do the allocation with sufficient alignment.
      (Likely exceptions include
      a template class with a base or member
      of a type that is a template parameter,
      and a derived class that inherits its allocation function
      from a base class,
      and also adds a member or base of over-aligned type.)</p>
  <p>If a global, alignment-aware allocation function is predeclared,
      then it will never be necessary
      to use a global, alignment-unaware allocation function
      for an over-aligned type;
      hence the brackets around item 4.</p>
  <p>It should be noted that an alignment-aware allocation function
      would be perfectly capable of performing an alignment
      that would suffice for an alignment-unaware function.
      In other words, from some perspective,
      it would make sense to let <code>operator new(size_t)</code>
    call <code>operator new(size_t, align_val_t)</code>,
      filling in the alignment value that it feels it needs to satisfy,
      and move the allocation loop to the alignment-aware function.
      But that would be pretty novel,
      so I have chosen not to propose it.</p>
  <div class="new">
    <h3>The allocation alignment threshold</h3>
    <p>At a joint EWG/CWG session in Jacksonville,
      it was agreed that the threshold above which to use 
      the new allocation routines should be
      the maximum alignment provided
      by the existing allocation routines,
      and that this value should be made available
      to the programmer.</p>
    <p>In this revision, I have chosen to use a predefined macro
      for this purpose.</p>
    <p>Unquestionably, the compiler needs to know this value.
      It's possible to imagine some magical way it could be learned
      from some library header,
      but it needs to be known
      even if no header has been included.
      And given the existence of independent implementations
      of the standard C++ library,
      pragmatically sometimes it will be the programmer who needs to 
      inform the compiler of this value at build time.
      To me, this set of requirements really suggests something
      an awful lot like a predefined macro.</p>
    <p>There is no reason why this value couldn't also be exposed
      (with a &ldquo;nicer&rdquo; name)
      by something in a library header.
      But I'm afraid that in real-world implementations,
      the actual value from the library would be provided
      by some macro anyway.</p>
    <p>So really, the only question is whether
      the predefined macro name appears in the standard,
      or is left for implementations to pick.
      And I think library implementers would be grateful
      if they didn't have to deal with
      different predefined macro names for different compilers.</p>
    <p>LEWG will eventually consider whether
      an additional non-macro name for this is justified.
      The absence of any such proposal in this revision
      should be taken as a sign of caution (or laziness)
      on my part, and not of prejudice or opposition.</p>
  </div>
  <h2>Proposed working draft changes</h2>
  <p>The following changes are relative to N4582 (post-Jacksonville).</p>
  <!--p>Mainly for simplicity,
    here I suggest that the new overloads
    should be added to <code>&lt;new&gt;</code>,
    and for consistency with that,
    that they should also be predeclared.
    But if 100% backward compatibility with C++14 is considered necessary,
    then the new overloads probably need to be declared
    in a new library header (possibly <code>&lt;aligned_new&gt;</code>).
    It's also possible to imagine
    requiring the declarations be in a new header,
    but making it implementation-defined whether that header
    is included by <code>&lt;new&gt;</code>,
    perhaps with the expectation
    that the actual choice will be left to users,
    under the control of a command-line option or macro setting.</p-->
  <p>There is one change of terminology worth noting.
    Today, the phrase &ldquo;placement new&rdquo; is ambiguous.
    In some contexts it means adding arguments
    to a call to an allocation function,
    with any types and unspecified purpose.
    In other contexts,
    it is used to refer specifically to cases
    where there is a single additional argument
    of type <code>void *</code>,
    in which case the allocation function
    doesn't actually allocate anything.
    I refer to the latter cases as &ldquo;non-allocating&rdquo;,
    and refer to &ldquo;allocating&rdquo; cases
    to distinguish them when necessary.</p>
  <p>Change 3.7.4p1:</p>
  <blockquote>
    <p>Objects can be created dynamically
	during program execution (1.9),
	using <var>new-expressions</var> (5.3.4), and
	destroyed using <var>delete-expressions</var> (5.3.5).
	A C++ implementation provides access to,
	and management of, dynamic storage
	via the global <dfn>allocation functions</dfn>
      <code>operator new</code> and <code>operator new[]</code>
      and the global <dfn>deallocation functions</dfn>
      <code>operator delete</code>
      and <code>operator delete[]</code>.
	<ins>[ <em>Note:</em> The non-allocating forms
	  described in [new.delete.placement]
	  do not perform allocation or deallocation.
	  &mdash;<em>end note</em>]</ins></p>
  </blockquote>
  <p>This is intended as a clarification
      of what seems already to be implied by [new.delete.placement]:</p>
  <blockquote>
    <p>The provisions of (3.7.4) do not apply
	to these reserved placement forms of
	<code>operator new</code> and <code>operator delete</code>.</p>
  </blockquote>
  <p>Change 3.7.4p2:</p>
  <blockquote>
    <p>The library provides default definitions
      for the global allocation and deallocation functions.
      Some global allocation and deallocation functions
      are replaceable (18.6.1).
      A C++ program shall provide at most one definition
      of a replaceable allocation or deallocation function.
      Any such function definition replaces the default version
      provided in the library (17.6.4.6).
      The following allocation and deallocation functions (18.6)
      are implicitly declared in global scope
      in each translation unit of a program.</p>
    <pre>void* operator new(std::size_t);
<ins>void* operator new(std::size_t, std::align_val_t);</ins>
void* operator new[](std::size_t);
<ins>void* operator new[](std::size_t, std::align_val_t);</ins>
void operator delete(void*);
<ins>void operator delete(void*, std::align_val_t);</ins>
void operator delete[](void*);
<ins>void operator delete[](void*, std::align_val_t);</ins>
void operator delete(void*, std::size_t);
<ins>void operator delete(void*, <span class="new">std::size_t, std::align_val_t</span>);</ins>
void operator delete[](void*, std::size_t);
<ins>void operator delete[](void*, <span class="new">std::size_t, std::align_val_t</span>);</ins></pre>
    <p>These implicit declarations introduce only the function names
      <code>operator new</code>, <code>operator new[]</code>,
      <code>operator delete</code>, and <code>operator delete[]</code>.
      [ <em>Note:</em> The implicit declarations do not introduce
      the names <code>std</code>,
      <code>std::size_t</code>,
      <ins><code>std::align_val_t</code>,</ins>
      or any other names that the library uses to declare these names.
      Thus, a <var>new-expression</var>, <var>delete-expression</var>
      or function call that refers to one of these functions
      without including the header <code>&lt;new&gt;</code>
      is well-formed.
      However, referring to <code>std</code> or
      <code>std::size_t</code>
      <ins>or <code>std::align_val_t</code></ins>
      is ill-formed unless the name has been declared
      by including the appropriate header.
      &mdash;<em>end note</em>]
      Allocation and/or deallocation functions <del>can</del>
      <ins>may</ins> also be declared and defined
      for any class (12.5).</p>
  </blockquote>
  <p class="new">The set of added functions is unchanged,
    but it was previously presented as a single cluster;
    the difference is editorial,
    but this ordering probably makes more sense.
    OTOH, a different order may make even more sense;
    see 18.6.1.</p>
  <p>Change 3.7.4.1p2:</p>
  <blockquote>
    <p>The allocation function attempts to allocate
      the requested amount of storage.
      If it is successful,
      it shall return the address
      of the start of a block of storage
      whose length in bytes shall be at least as large
      as the requested size.
      There are no constraints on the contents
      of the allocated storage on return from the allocation function.
      The order, contiguity, and initial value of storage
      allocated by successive calls to an allocation function
      are unspecified.
      The pointer returned shall be suitably aligned
      so that it can be converted to a pointer <del>of</del>
      <ins>to</ins> any <ins>suitable</ins> complete object type
      <ins>([new.delete.single])</ins>
      <del>with a fundamental alignment requirement (3.11)</del>
      and then used to access the object or array
      in the storage allocated
      (until the storage is explicitly deallocated
      by a call to a corresponding deallocation function).
      Even if the size of the space requested is zero,
      the request can fail.
      If the request succeeds,
      the value returned shall be
      a non-null pointer value (4.10) <code>p0</code>
      different from any previously returned value <code>p1</code>,
      unless that value <code>p1</code> was subsequently passed
      to an <code>operator delete</code>.
      Furthermore, for the library allocation functions
      in 18.6.2.1 and 18.6.2.2,
      <code>p0</code> shall point to a block of storage
      disjoint from the storage for any other object
      accessible to the caller.
      The effect of indirecting through a pointer
      returned as a request for zero size is undefined.<sup>36</sup></p>
  </blockquote>
  <p>The text here is intentionally made less specific,
    with the details to be found elsewhere.</p>
  <p>Change 3.7.4.2p2:</p>
  <blockquote>
    <p>Each deallocation function shall return <code>void</code>
      and its first parameter shall be <code>void*</code>.
	A deallocation function <del>can</del> <ins>may</ins> have
	more than one parameter.
	<del>The global <code>operator delete</code>
	  with exactly one parameter
	    is a usual (nonplacement) deallocation function.
	    The global <code>operator delete</code>
	  with exactly two parameters,
	    the second of which has type <code>std::size_t</code>,
	    is a usual deallocation function.
	    Similarly, the global <code>operator delete[]</code>
	  with exactly one parameter
	    is a usual deallocation function.
	    The global <code>operator delete[]</code>
	  with exactly two parameters,
	    the second of which has type <code>std::size_t</code>,
	    is a usual deallocation function.<sup>37</sup>
	  If a class <code>T</code>
	  has a member deallocation function
	    named <code>operator delete</code>
	  with exactly one parameter,
	    then that function is a usual deallocation function.
	    If class <code>T</code> does not declare
	    such an <code>operator delete</code> but does declare
	    a member deallocation function
	    named <code>operator delete</code>
	  with exactly two parameters,
	    the second of which has type <code>std::size_t</code>,
	    then this function is a usual deallocation function.
	    Similarly, if a class <code>T</code>
	  has a member deallocation function
	    named <code>operator delete[]</code>
	  with exactly one parameter,
	    then that function is
	    a usual (non-placement) deallocation function.
	    If class <code>T</code> does not declare
	    such an <code>operator delete[]</code> but does declare
	    a member deallocation function
	    named <code>operator delete[]</code>
	  with exactly two parameters,
	    the second of which has type <code>std::size_t</code>,
	    then this function is a usual deallocation function.</del>
      <ins>A <dfn>usual deallocation function</dfn>
	is a deallocation function that has:</ins></p>
    <ins>
      <ul>
	<li>exactly one parameter; or</li>
	<li>exactly two parameters,
	    the type of the second being
	    either <code>std::align_val_t</code>
	  or <code>std::size_t</code><sup>37)</sup>; or</li>
	<li>exactly three parameters,
	    the type of the second being <code class="new">std::size_t</code>
	  and the type of the third
	    being <code class="new">std::align_val_t</code>.</li>
      </ul>
    </ins>
    <p><em>Footnote:</em>
      37) <del>This deallocation function</del>
      <ins>The global
	  <code>operator delete(void*, std::size_t)</code></ins>
      precludes use
	of an allocation function
	<code>void operator new(std::size_t, std::size_t)</code>
      as a placement allocation function (C.3.2).</p>
    <p>A deallocation function <del>can</del> <ins>may</ins>
      be an instance of a function template.
	Neither the first parameter nor the return type
	shall depend on a template parameter.
	[ <em>Note:</em> That is, a deallocation function template
	shall have a first parameter of type <code>void*</code>
      and a return type of <code>void</code>
      (as specified above). <em>&mdash;end note</em> ]
	A deallocation function template
	shall have two or more function parameters.
	A template instance is never a usual deallocation function,
	regardless of its signature.</p>
  </blockquote>
  <p>Adding the new overloads
      to the set of "usual" deallocation functions
      in the same style as the previous formulation
      would have required outrageous verbosity.
      My new formulation is much more concise
      and (to my eyes) comprehensible,
      but there is a technical difference worth noting.</p>
  <p>Previously, in class scope, if deallocation functions
      with and without a size parameter are both declared,
      the one with the size parameter was not "usual".
      My simpler formulation includes both overloads.
      But it is not difficult to tweak the selection algorithm
      (5.3.5p10)
      to produce the same result as previously.</p>
  <p>Change 3.7.4.2p3:</p>
  <blockquote>
    <p>If a deallocation function terminates by throwing an exception,
      the behavior is undefined.
      The value of the first argument
      supplied to a deallocation function
      may be a null pointer value;
      if so, and if the deallocation function
      is one supplied in the standard library,
      the call has no effect.
      <del>Otherwise, the behavior is undefined
	if the value supplied to <code>operator delete(void*)</code>
	in the standard library is not one of the values
	returned by a previous invocation
	of either <code>operator new(std::size_t)</code>
	or <code>operator new(std::size_t,
	const std::nothrow_t&amp;)</code>
	in the standard library, and the behavior is undefined
	if the value supplied to <code>operator delete[](void*)</code>
	in the standard library is not one of the values returned
	by a previous invocation
	of either <code>operator new[](std::size_t)</code>
	or <code>operator new[](std::size_t,
	  const std::nothrow_t&amp;)</code>
	in the standard library.</del></p>
  </blockquote>
  <p>These requirements apply only to the library implementations,
    and are already stated in 18.6.</p>
  <p>Change 3.7.4.3p2:</p>
  <blockquote>
    <p>A pointer value is a <dfn>safely-derived pointer</dfn>
      to a dynamic object only if
      it has an object pointer type and it is one of the following:</p>
    <ul>
      <li>the value returned by a call
	to the C++ standard library implementation of
	<code>::operator new(std::size_t)</code>
	<ins>or <code>::operator new(std::size_t,
	  std::align_val_t)</code></ins>;<sup>39</sup></li>
      <li>...</li>
    </ul>
  </blockquote>
  <p>Change 3.9.2p3:</p>
  <blockquote>
    <p>... [ <em>Note:</em>
      Pointers to over-aligned types (3.11)
      have no special representation,
      but their range of valid values is restricted
      by the extended alignment requirement.
      <del>This International Standard specifies only two ways
	of obtaining such a pointer:
	taking the address of a valid object
	with an over-aligned type,
	and using one of the runtime pointer alignment functions.
	An implementation may provide other means
	of obtaining a valid pointer value
	for an over-aligned type.</del>
      &mdash;<em>end note</em> ]</p>
  </blockquote>
  <p>Change 3.11p3:</p>
  <blockquote>
    <p class="new">An <dfn>extended alignment</dfn> is represented by an alignment greater than <code>alignof(std::max_align_t)</code>.
       It is implementation-defined whether any extended alignments are supported and the contexts in which they
are supported (7.6.2).
      A type having an extended alignment requirement is an <dfn>over-aligned type</dfn>.
      <ins>A <dfn>new-extended alignment</dfn> is represented by
	an alignment greater than <code>__STDCPP_DEFAULT_NEW_ALIGNMENT__</code>.</ins>
      [ <em>Note:</em>
      every over-aligned type is or contains a class type to which extended alignment applies (possibly through a
non-static data member).
      &mdash;<em>end note</em> ]</p>
  </blockquote>
  <p>Change 5.3.4p1:</p>
  <blockquote>
    <p>The <var>new-expression</var> attempts to create
	an object of the <var>type-id</var> (8.1)
	or <var>new-type-id</var>
      to which it is applied.
	The type of that object is the <dfn>allocated type</dfn>.
	This type shall be a complete object type,
	but not an abstract class type
	or array thereof (1.8, 3.9, 10.4).
	<del>It is implementation-defined whether over-aligned types
	are supported (3.11).</del> [ <em>Note:</em> ...</p>
  </blockquote>
  <p>Change 5.3.4p8:</p>
  <blockquote>
    <p>A <var>new-expression</var> may obtain storage
	for the object by calling an allocation function (3.7.4.1).
	If the <var>new-expression</var> terminates
	by throwing an exception,
	it may release storage
	by calling a deallocation function (3.7.4.2).
	If the allocated type is a non-array type,
	the allocation function's name
	is <code>operator new</code>
      and the deallocation function's name
	is <code>operator delete</code>.
	If the allocated type is an array type,
	the allocation function's name
	is <code>operator new[]</code>
      and the deallocation function's name
	is <code>operator delete[]</code>.
	[ <em>Note:</em>
      an implementation shall provide default definitions
	for the global allocation functions (3.7.4, 18.6.2.1, 18.6.2.2).
	A C++ program can provide alternative definitions
	of these functions (17.6.4.6)
	and/or class-specific versions (12.5).
	<ins>The set of allocation and deallocation functions
	  that may be called by a <var>new-expression</var> may
	  include functions that do not perform allocation or deallocation;
	  for example, see [new.delete.placement].</ins>
      &mdash;<em>end note</em> ]</p>
  </blockquote>
  <p>As an editorial matter,
    note that the current WD inappropriately uses italics
    for the first occurrence of &ldquo;allocation function&rdquo;
    in this paragraph;
    the italics should be removed.</p>
  <p>Change 5.3.4p13:</p>
  <blockquote>
    <p>The <var>new-placement</var> syntax is used
      to supply additional arguments
      to an allocation function<ins>;
	such an expression is called
	a <dfn>placement new-expression</dfn></ins>.
      <del>If used, overload</del> <ins>Overload</ins> resolution
      is performed on a function call
      created by assembling an argument list<ins>.</ins>
      <del>consisting of</del>
      <ins>The first argument is</ins> the amount of space requested
      <del>(the first argument)</del>
      <ins>, and has type <code>std::size_t</code>.
      If the type of the allocated object
	has new-extended alignment,
      the next argument is the type's alignment,
      and has type <code>std::align_val_t</code>.</ins>
      <del>and the</del>
      <ins>If the <var>new-placement</var> syntax is used, its</ins>
      expressions
      <del>in the <var>new-placement</var> part
	of the <var>new-expression</var> (</del>
      <ins>are the</ins> <del>second and</del> succeeding arguments<del>)</del>.
      <del>The first of these arguments has type <code>std::size_t</code>
	and the remaining arguments have the corresponding types
	  of the expressions in the <var>new-placement</var>;
	such an expression is called
	a <dfn>placement new-expression</dfn>.</del>
      <ins>If no matching function is found
	and the allocated object type
	has new-extended alignment,
	the alignment argument is removed from the argument list,
	and overload resolution is performed again.</ins></p>
  </blockquote>
  <p>Change 5.3.4p14:</p>
  <blockquote>
    <p>[ <em>Example:</em></p>
    <ul>
      <li><code>new T</code> results in a call of <ins>either</ins>
	<code>operator new(sizeof(T))</code>
	<ins>or <code>operator new(sizeof(T),
	  std::align_val_t(alignof(T)))</code></ins>,</li>
      <li><code>new(2,f) T</code> results in a call of <ins>either</ins>
	<code>operator new(sizeof(T),2,f)</code>
	<ins>or <code>operator new(sizeof(T),
	  std::align_val_t(alignof(T)),2,f)</code></ins>,</li>
      <li><code>new T[5]</code> results in a call of <ins>either</ins>
	<code>operator new[](sizeof(T)*5+x)</code>
	<ins>or <code>operator new[](sizeof(T)*5+x,
	  std::align_val_t(alignof(T)))</code></ins>, and</li>
      <li><code>new(2,f) T[5]</code> results in a call of
	<ins>either</ins>
	<code>operator new[](sizeof(T)*5+<del>y</del><ins>x</ins>,2,f)</code>
	<ins>or <code>operator new[](sizeof(T)*5+x,
	  std::align_val_t(alignof(T)),2,f)</code></ins>.</li>
    </ul>
    <p>Here, <ins>each instance of</ins> <code>x</code>
      <del>and y are</del> <ins>is a</ins> non-negative unspecified
      <del>values</del> <ins>value</ins>
      representing array allocation overhead; ...
      &mdash; <em>end example</em> ]</p>
  </blockquote>
  <p>Change 5.3.4p15:</p>
  <blockquote>
    <p>[ <em>Note</em>:
      unless an allocation function
      has a non-throwing exception specification (15.4),
      it indicates failure to allocate storage
      by throwing a <code>std::bad_alloc</code> exception
      (3.7.4.1, Clause 15, 18.6.3.1);
      it returns a non-null pointer otherwise.
      If the allocation function
      has a non-throwing exception specification,
      it returns null to indicate failure to allocate storage
      and a non-null pointer otherwise.
      &mdash;<em>end note</em> ]
      If the allocation function is a
      <del>reserved placement allocation function</del>
      <ins>non-allocating form</ins> (18.6.2.3)
      that returns null, the behavior is undefined.
      Otherwise, if the allocation function returns null,
      initialization shall not be done,
      the deallocation function shall not be called,
      and the value of the <var>new-expression</var>
      shall be null.</p>
  </blockquote>
  <p>Change 5.3.4p22:</p>
  <blockquote>
    <p>A declaration of a placement deallocation function
	matches the declaration of a placement allocation function
	if it has the same number of parameters and,
	after parameter transformations (8.3.5),
	all parameter types except the first are identical.
	If the lookup finds a single matching deallocation function,
	that function will be called;
	otherwise, no deallocation function will be called.
	If the lookup finds <del>the two-parameter form of</del>
      a usual deallocation function
	<ins class="new">with a parameter
	  of type <code>std::size_t</code></ins> (3.7.4.2)
	and that function,
	considered as a placement deallocation function,
	would have been selected as a match
	for the allocation function,
	the program is ill-formed.
	For a non-placement allocation function,
	the normal deallocation function lookup is used
	to find the matching deallocation function (5.3.5)
      [ <em>Example</em>:</p>
  </blockquote>
  <!--p>Change 5.3.5p5:</p>
  <blockquote>
    <p class="new">If the object being deleted
	has incomplete class type at the point of deletion<ins>,</ins>
      and the complete class
	<ins>has new-extended alignment,</ins>
      has a non-trivial destructor<ins>,</ins>
      or <ins>has</ins> a deallocation function,
	the behavior is undefined.</p>
  </blockquote-->
  <!--    <p>Consider whether to change 17.6.3.5p10:</p>
    <blockquote>
      <p>If the alignment associated with a specific over-aligned type
	is not supported by an allocator,
	instantiation of the allocator for that type may fail.
	The allocator also may silently ignore the requested alignment.
	[ <em>Note:</em>
	Additionally, the member function <code>allocate</code>
	for that type may fail by throwing
	an object of type <code>std::bad_alloc</code>.
	&mdash;<em>end note</em> ]</p>
    </blockquote>
    <p>Even if the standard allocator is required
      to handle arbitrary alignments,
      it may be reasonable not to make the same requirement
      of user-defined allocators.</p>-->
  <p>Change 5.3.5p10:</p>
  <blockquote>
    <p>If deallocation function lookup finds <del>both
	a</del> <ins>more than one</ins> usual deallocation function
	<del>with only a pointer parameter and
	a usual deallocation function with both a pointer parameter
	and a size parameter</del>,
	the function to be called is selected as follows:</p>
    <ul>
      <li><ins>If the type has new-extended alignment,
	    a function with
	<span class="new">a parameter
	  of type <code>std::align_val_t</code></span> is preferred;
	    otherwise a function <span class="new">without such a parameter</span>
	    is preferred.
	    If exactly one preferred function is found,
	    that function is selected
	    and the selection process terminates.
	    If more than one preferred function is found,
	    all non-preferred functions
	    are eliminated from further consideration.</ins></li>
      <li><ins>If the deallocation functions have class scope,
	    the one without a <span class="new">parameter of type <code>std::size_t</code></span> is selected.</ins></li>
      <li>If the type is complete and if,
	  for the second alternative (delete array) only,
	  the operand is a pointer to a class type
	  with a non-trivial destructor
	  or a (possibly multi-dimensional) array thereof,
	  the function with <del>two parameters</del>
	<ins class="new">a parameter of type <code>std::size_t</code></ins> is selected.</li>
      <li>Otherwise, it is unspecified
	  <del>which of the two deallocation functions</del>
	<ins>whether a deallocation function
	    with a <span class="new">parameter of type <code>std::size_t</code></span></ins> is selected.</li>
    </ul>
  </blockquote>
  <p>Change 5.3.5p11:</p>
  <blockquote>
    <p>When a <var>delete-expression</var> is executed,
	the selected deallocation function shall be called
	with the address of the block of storage to be reclaimed
	as its first argument<ins>.
	  If a deallocation function with a <span class="new">parameter of type <code>std::align_val_t</code></span>
	  is used,
	  the alignment of the type
	  of the object to be deleted
	  is passed
	  as the corresponding argument.</ins>
      <del>and (if the two-parameter</del>
      <ins>If a</ins>
      deallocation function
	<ins class="new">with a parameter of type <code>std::size_t</code></ins>
      is used<del>)</del><ins>,</ins>
      the size of the block <ins>is passed</ins>
      as <del>its second</del>
      <ins>the corresponding</ins> argument.<sup>82</sup></p>
  </blockquote>
  <p>Add a new predefined macro to the list in 16.8p1:</p>
  <blockquote>
    <dl class="new">
      <dt><ins><code>__STDCPP_DEFAULT_NEW_ALIGNMENT__</code></ins></dt>
      <dd><ins>An integer literal of type <code>size_t</code>
	whose value is the alignment guaranteed by a call to
	<code>operator new(std::size_t)</code> or
	<code>operator new[](std::size_t)</code>.
	[ <em>Note:</em> Larger alignments will be passed to <code>operator
	new(std::size_t, std::align_val_t)</code>, etc.
	([expr.new]). &mdash; <em>end note</em>]</ins></dd>
    </dl>
  </blockquote>
  <p>Change 17.6.4.6p2:</p>
  <blockquote>
    <p>A C++ program may provide the definition
      for any of the following
      dynamic memory allocation function signatures
      declared in header <code>&lt;new&gt;</code> (3.7.4, 18.6):</p>
    <ul>
      <li><code>operator new(std::size_t)</code></li>
      <li><code>operator new(std::size_t,
		const std::nothrow_t&amp;)</code></li>
      <li><ins><code>operator new(std::size_t,
		    std::align_val_t)</code></ins></li>
      <li><ins><code>operator new(std::size_t, std::align_val_t,
		    const std::nothrow_t&amp;)</code></ins></li>
      <li><code>operator new[](std::size_t)</code></li>
      <li><code>operator new[](std::size_t,
		const std::nothrow_t&amp;)</code></li>
      <li><ins><code>operator new[](std::size_t,
		    std::align_val_t)</code></ins></li>
      <li><ins><code>operator new[](std::size_t, std::align_val_t,
		    const std::nothrow_t&amp;)</code></ins></li>
      <li><code>operator delete(void*)</code></li>
      <li><code>operator delete(void*,
		const std::nothrow_t&amp;)</code></li>
      <li><code>operator delete(void*, std::size_t)</code></li>
      <li><ins><code>operator delete(void*, std::align_val_t)</code></ins></li>
      <li><ins><code>operator delete(void*, std::align_val_t,
		    const std::nothrow_t&amp;)</code></ins></li>
      <li><ins><code>operator delete(void*,
		    <span class="new">std::size_t, std::align_val_t</span>)</code></ins></li>
      <li><code>operator delete[](void*)</code></li>
      <li><code>operator delete[](void*,
		const std::nothrow_t&amp;)</code></li>
      <li><code>operator delete[](void*, std::size_t)</code></li>
      <li><ins><code>operator delete[](void*,
		    std::align_val_t)</code></ins></li>
      <li><ins><code>operator delete[](void*, std::align_val_t,
		    const std::nothrow_t&amp;)</code></ins></li>
      <li><ins><code>operator delete[](void*,
		    <span class="new">std::size_t, std::align_val_t</span>)</code></ins></li>
    </ul>
  </blockquote>
  <p>Change 18.6.1:</p>
  <blockquote>
    <pre>namespace std {
    class bad_alloc;
    class bad_array_new_length;
    <ins>enum class align_val_t: size_t {};</ins>
    struct nothrow_t {};
    extern const nothrow_t nothrow;
    typedef void (*new_handler)();
    new_handler get_new_handler() noexcept;
    new_handler set_new_handler(new_handler new_p) noexcept;

    // <em>18.6.4, hardware interference size</em>
    static constexpr size_t hardware_destructive_interference_size =
       <var>implementation-defined</var> ;
    static constexpr size_t hardware_constructive_interference_size =
       <var>implementation-defined</var> ;
};</pre>
    <pre>void* operator new(std::size_t size);
<ins>void* operator new(std::size_t size, std::align_val_t alignment);</ins>
void* operator new(std::size_t size, const std::nothrow_t&amp;) noexcept;
<ins>void* operator new(std::size_t size, std::align_val_t alignment,</ins>
			<ins>const std::nothrow_t&amp;) noexcept;</ins>
void operator delete(void* ptr) noexcept;
void operator delete(void* ptr, std::size_t size) noexcept;
<ins>void operator delete(void* ptr, std::align_val_t alignment) noexcept;</ins>
<ins>void operator delete(void* ptr, <span class="new">std::size_t size</span>,</ins>
			<ins><span class="new">std::align_val_t alignment</span>) noexcept;</ins>
void operator delete(void* ptr, const std::nothrow_t&amp;) noexcept;
<ins>void operator delete(void* ptr, std::align_val_t alignment,</ins>
			<ins>const std::nothrow_t&amp;) noexcept;</ins>
void* operator new[](std::size_t size);
<ins>void* operator new[](std::size_t size, std::align_val_t alignment);</ins>
void* operator new[](std::size_t size, const std::nothrow_t&amp;) noexcept;
<ins>void* operator new[](std::size_t size, std::align_val_t alignment,</ins>
			<ins>const std::nothrow_t&amp;) noexcept;</ins>
void operator delete[](void* ptr) noexcept;
void operator delete[](void* ptr, std::size_t size) noexcept;
<ins>void operator delete[](void* ptr, std::align_val_t alignment) noexcept;</ins>
<ins>void operator delete[](void* ptr, <span class="new">std::size_t size</span>,</ins>
			<ins><span class="new">std::align_val_t alignment</span>) noexcept;</ins>
void operator delete[](void* ptr, const std::nothrow_t&amp;) noexcept;
<ins>void operator delete[](void* ptr, std::align_val_t alignment,</ins>
			<ins>const std::nothrow_t&amp;) noexcept;</ins></pre>
    <pre>void* operator new&nbsp;&nbsp;(std::size_t size, void* ptr) noexcept;
void* operator new[](std::size_t size, void* ptr) noexcept;
void operator delete&nbsp;&nbsp;(void* ptr, void*) noexcept;
void operator delete[](void* ptr, void*) noexcept;</pre>
  </blockquote>
  <p class="new">I have carefully added the new overloads
    in the synopsis to appear in the same order
    that they are described below.
    Unfortunately, that required moving the declarations
    of <code>nothrow</code> deallocation functions;
    that's an editorial change that I didn't explicitly mark above.
    I also noticed that the lists in 3.7.4 and 17.6.4.6
    are ordered differently than this one,
    and for that matter that the list in 17.6.4.6 has bullets;
    editorially, it may be desirable for these lists
    to be more consistent with one another.</p>
  <p>Change 18.6.2p1:</p>
  <blockquote>
    <p class="new">Except where otherwise specified,
	the provisions of (3.7.4) apply
	to the library versions of <code>operator new</code>
      and <code>operator delete</code>.
	<ins>If the value of an alignment argument
	  passed to any of these functions
	  is not a valid alignment value,
	  the behavior is undefined.</ins>
    </p>
  </blockquote>
  <p class="new">There was a provision about the size
    being a multiple of the alignment, which
    was added in response to a comment
    made in CWG at the Jacksonville meeting.
    However, Martin Sebor, who has also been working
    on aligned allocation for C,
    pointed out that it unnecessarily complicates
    the following technique:</p>
  <pre class="new">typedef struct S {
    _Alignas(64) int a[16];
    char x[];
} S;

S *s = aligned_alloc(_Alignof(S), sizeof(S) + 20);</pre>
  <p class="new">The provision basically assumed that
    the only way a block of allocated memory can be used
    is by filling it with an array
    (of elements all having the same type).
    But raw memory is (or at least ought to be)
    more flexible than that.
    LWG agreed that it made sense to remove that provision.</p>
  <p>Change section 18.6.2.1 as follows.
      (Some technically irrelevant editorial improvements are included;
      in CWG, these would be called &ldquo;en passant&rdquo;
      or &ldquo;drive-by&rdquo; changes.
    Also, there are some inappropriate uses
      of italics in these two sections which should be fixed,
      for phrases including
      &ldquo;allocation function&rdquo;,
      &ldquo;deallocation function&rdquo;,
      and &ldquo;ptr&rdquo;.)
  </p>
  <blockquote>
    <h4>18.6.2.1 Single-object forms</h4>
    <p class="decl"><code>void* operator new(std::size_t size);<br />
      <ins>void* operator new(std::size_t size,
		    std::align_val_t alignment);</ins></code></p>
    <p class="numbered"><em>Effects:</em>
      The allocation <del>function</del> <ins>functions</ins>
      ([basic.stc.dynamic.allocation])
	called by a <var>new-expression</var> ([expr.new])
	to allocate <code>size</code> bytes of storage<ins>.
	The second form is called for a type with new-extended alignment,
	  and allocates storage
	  with the specified alignment.
      The first form is called otherwise,
	and allocates storage</ins>
      suitably aligned to represent any object of that size
      <ins>provided the object's type does not have
	new-extended alignment</ins>.</p>
    <p class="numbered"><em>Replaceable:</em>
      a C++ program may define
	<del>a function with this function signature
          that displaces</del>
      <ins>functions with either of these function signatures,
          and thereby displace</ins>
      the default <del>version</del> <ins>versions</ins>
      defined by the C++ standard library.</p>
    <p class="numbered">
      <em>Required behavior:</em>
      Return a non-null pointer
	to suitably aligned storage ([basic.stc.dynamic]),
	or else throw a <code>bad_alloc</code> exception.
	This requirement is binding on <del>a</del> <ins>any</ins>
      replacement <del>version</del> <ins>versions</ins>
      of <del>this function</del> <ins>these functions</ins>.</p>
    <p class="numbered"><em>Default behavior:</em></p>
    <ul>
      <li>Executes a loop:
	  Within the loop,
	  the function first attempts to allocate
	  the requested storage.
	  Whether the attempt involves a call
	  to the Standard C library <del>function</del> <ins>functions</ins>
	<code>malloc</code>
	<ins>or <code>aligned_alloc</code></ins>
	is unspecified.</li>
      <li>Returns a pointer to the allocated storage
	  if the attempt is successful.
	  Otherwise, if the
	  current <code>new_handler</code> ([get.new.handler]) is
	  a null pointer value, throws
	  <code>bad_alloc</code>.</li>
      <li>Otherwise, the function calls the current
	  <code>new_handler</code> function ([new.handler]).
	  If the called function returns, the loop repeats.</li>
      <li>The loop terminates when an attempt to allocate
	  the requested storage is
	  successful or when a called
	  <code>new_handler</code>
	function does not return.</li>
    </ul>
    <p class="decl"><code>void* operator new(std::size_t size,
		const std::nothrow_t&amp;) noexcept;<br />
      <ins>void* operator new(std::size_t size,
		    std::align_val_t alignment,
		    const std::nothrow_t&amp;) noexcept;</ins></code></p>
    <p class="numbered"><em>Effects:</em>
      Same as above, except that <del>it is</del>
      <ins>these are</ins>
      called by a placement version of a <var>new-expression</var>
      when a C++ program prefers a null pointer result
	as an error indication,
	instead of a <code>bad_alloc</code> exception.</p>
    <p class="numbered"><em>Replaceable:</em>
      a C++ program may define a function
	with this function signature
	that displaces the default version defined by the
	C++ standard library.
	<span class="ed">This should be changed similarly
	    to paragraph 2.</span></p>
    <p class="numbered"><em>Required behavior:</em>
      Return a non-null pointer
	to suitably aligned storage ([basic.stc.dynamic]),
	or else return a null pointer.
	<del>This</del> <ins>Each of these</ins> nothrow
	<del>version</del> <ins>versions</ins> of
	<code>operator new</code>
      returns a pointer
	obtained as if acquired
	from the (possibly replaced) <del>ordinary version</del>
      <ins>corresponding non-placement function</ins>.
	This requirement is binding on a
	replacement version
	of this function.
	<span class="ed">The last sentence should be changed
	    similarly to paragraph 3.</span></p>
    <p class="numbered"><em>Default behavior:</em>
      Calls <code>operator new(size)</code><ins>,
	or <code>operator new(size, alignment)</code>, respectively</ins>.
	If the call returns normally,
	returns the result of that call.
	Otherwise, returns a null pointer.</p>
    <p class="numbered">[ <em>Example:</em></p>
    <pre>T* p1 = new T; // throws bad_alloc if it fails
T* p2 = new(nothrow) T; // returns nullptr if it fails</pre>
    <p>&mdash;<em>end example</em> ]</p>
    <p class="decl"><code>void operator delete(void* ptr) noexcept;<br />
      void operator delete(void* ptr,
		std::size_t size) noexcept;<br />
      <ins>void operator delete(void* ptr,
		    std::align_val_t alignment) noexcept;<br />
	void operator delete(void* ptr,
		    <span class="new">std::size_t size,
		    std::align_val_t alignment</span>) noexcept;</ins>
    </code></p>
    <p class="numbered"><em>Effects:</em>
      The deallocation <del>function</del> <ins>functions</ins> ([basic.stc.dynamic.deallocation])
	called by a <var>delete-expression</var>
      to render the value of <code>ptr</code> invalid.</p>
    <p class="numbered">
      <em>Replaceable:</em>
      a C++ program may define
	<del>a function with signature
	<code>void operator delete(void* ptr) noexcept</code>
	  that displaces</del>
      <ins>functions with any of these signatures,
	and thereby displace</ins>
      the default version<ins>(s)</ins> defined by the
	C++ standard library.
	If <del>this</del> <ins>a</ins> function
	<del>(</del>without <ins>a</ins>
      <code>size</code> parameter<del>)</del>
      is defined,
	the program should also define
	<del><code>void operator delete(void* ptr,
	    td::size_t size) noexcept</code></del>
      <ins>the corresponding function
	  with a <code>size</code> parameter</ins>.
	If <del>this</del> <ins>a</ins> function
	with <ins>a</ins> <code>size</code> parameter is defined,
	the program shall also define
	the <ins>corresponding</ins> version
	without the <code>size</code> parameter.
	[ <em>Note:</em> The default behavior below
	may change in the future,
	which will require replacing both deallocation functions
	when replacing the allocation function.
	&mdash;<em>end note</em> ]</p>
    <p class="numbered"><em>Requires:</em>
      <code>ptr</code> shall be a null pointer or
	its value shall <del>be a value returned</del>
      <ins>point to a block of memory allocated</ins> by an
	earlier call to <del>the</del> <ins>a</ins> (possibly replaced)
	<code>operator new(std::size_t)</code>
      or
	  <code>operator new(std::size_t,
	    <del>const std::nothrow_t&amp;</del> <ins>std::align_val_t</ins>)</code>
      which has not been invalidated by an intervening call to
	<code>operator delete<del>(void*)</del></code> <del>or
	    <code>operator delete(void*, std::size_t)</code></del>.</p>
    <p class="numbered"><em>Requires:</em>
      If an implementation
	has strict pointer safety ([basic.stc.dynamic.safety])
	then <code>ptr</code> shall be a safely-derived pointer.</p>
    <p class="numbered"><em>Requires:</em>
      <ins>If the <code>alignment</code> parameter is not present,
	  <code>ptr</code> shall have been returned
	  by an allocation function
	  <span class="new">without an <code>alignment</code> parameter</span>.
	  If present, the <code>alignment</code> argument shall equal
	  the alignment argument passed to the allocation function
	  that returned <code>ptr</code>.</ins>
      If present,
	the <code><del>std::size_t</del> size</code> argument
	shall equal the size argument passed to the allocation function
	that returned <code>ptr</code>.</p>
    <p class="numbered"><em>Required behavior:</em>
      <del>Calls</del> <ins>A call</ins> to <ins>an</ins>
      <code>operator delete<del>(void* ptr,
		    std::size_t size)</del></code>
      <ins class="new">with a <code>size</code> parameter</ins>
      may be changed to <del>calls</del> <ins>a call</ins> to
	<ins>the corresponding</ins>
      <code>operator delete<del>(void* ptr)</del></code>
      <ins class="new">without a <code>size</code> parameter,</ins>
      without affecting memory allocation.
	[ <em>Note:</em> A conforming implementation is for
	<code>operator delete(void* ptr,
	    std::size_t size)</code> to simply call
	<code>operator delete(ptr)</code>.
	&mdash;<em>end note</em> ]</p>
    <p class="numbered">
      <em>Default behavior:</em>
      the function
	<code>operator delete(void* ptr, std::size_t size)</code> calls
	<code>operator delete(ptr)</code>.
	<ins>The function
	<code>operator delete(void* ptr,
	    std::align_val_t alignment, std::size_t)</code> calls
	<code>operator delete(ptr, alignment)</code>.</ins>
      [ <em>Note:</em> See the note
	in the above <em>Replaceable</em> paragraph.
	&mdash;<em>end note</em> ]</p>
    <p class="numbered">
      <em>Default behavior:</em>
      If <code>ptr</code> is null, does nothing.
	Otherwise, reclaims the storage allocated
	by the earlier call to <code>operator new</code>.</p>
    <p class="ed">The previous revision suggested changing
    &ldquo;Default behavior&rdquo; to &ldquo;Required behavior&rdquo;.
    I am walking back from that suggestion,
    not because I think it was wrong,
    but simply because it has nothing to do with alignment.
    If that should be done, let it be done as a separate effort.</p>
    <p class="numbered"><em>Remarks:</em>
      It is unspecified under what conditions part or all of such
	reclaimed storage will be allocated by subsequent calls to
	<code>operator new</code>
      or any of
	<ins><code>aligned_alloc</code>,</ins>
      <code>calloc</code>,
	<code>malloc</code>,
	or
	<code>realloc</code>,
	declared in
	<code>&lt;cstdlib&gt;</code>.</p>
    <p class="decl">
      <code>void operator delete(void* ptr,
		    const std::nothrow_t&amp;) noexcept;<br />
	<ins>void operator delete(void* ptr,
			std::align_val_t alignment,
			const std::nothrow_t&amp;) noexcept;</ins></code>
    </p>
    <p class="numbered"><em>Effects:</em>
      The deallocation <del>function</del> <ins>functions</ins> ([basic.stc.dynamic.deallocation])
	called by the implementation
	to render the value of <code>ptr</code> invalid
	when the constructor invoked
	from a nothrow placement version
	of the <var>new-expression</var> throws an exception.</p>
    <p class="numbered"><em>Replaceable:</em>
      a C++ program may define <del>a function</del> <ins>functions</ins> with
	<del>signature
	<code>void operator delete(void* ptr,
	    const std::nothrow_t&amp;) noexcept</code>
	  that displaces</del>
      <ins>any of these signatures, and thereby displace</ins>
      the default version<ins>(s)</ins>
      defined by the C++ standard library.</p>
    <p class="numbered new"><ins><em>Requires:</em>
      <code>ptr</code> shall be a null pointer or
	its value shall 
      point to a block of memory allocated by an
	earlier call to a (possibly replaced)
	<code>operator new(std::size_t)</code>
      or
	  <code>operator new(std::size_t,
std::align_val_t)</code>
      which has not been invalidated by an intervening call to
	<code>operator delete</code>.</ins></p>
    <p class="numbered"><em>Requires:</em>
      If an implementation
	has strict pointer safety ([basic.stc.dynamic.safety])
	then <code>ptr</code> shall be a safely-derived pointer.</p>
    <p class="numbered new"><ins><em>Requires:</em>
      If the <code>alignment</code> parameter is not present,
	  <code>ptr</code> shall have been returned
	  by an allocation function
	  without an <code>alignment</code> parameter.
	  If present, the <code>alignment</code> argument shall equal
	  the alignment argument passed to the allocation function
	  that returned <code>ptr</code>.</ins></p>
    <p class="numbered"><em>Default behavior:</em>
      <ins>The function</ins> <code>operator delete(void* ptr,
	    const std::nothrow_t&amp;)</code> calls
	<code>operator delete(ptr)</code>.
	<ins>The function <code>operator delete(void* ptr,
	    std::align_val_t alignment,
	    const std::nothrow_t&amp;)</code> calls
	<code>operator delete(ptr, alignment)</code>.</ins></p>
  </blockquote>
  <p>Change section 18.6.2.2:</p>
  <blockquote>
    <h4>18.6.2.2 Array forms</h4>
    <p class="decl"><code>void* operator new[](std::size_t size);<br />
      <ins>void* operator new[](std::size_t size,
		  std::align_val_t alignment);</ins></code></p>
    <p class="numbered"><em>Effects:</em>
      The allocation <del>function</del>
      <ins>functions</ins> ([basic.stc.dynamic.allocation])
	called by the array form of a
	<var>new-expression</var> ([expr.new])
	to allocate <code>size</code> bytes of storage<ins>.
	The second form is called for a type with new-extended alignment,
	  and allocates storage
	  with the specifed alignment.
      The first form is called otherwise,
	and allocates storage</ins>
      suitably aligned to represent any array
	object of that size or smaller<ins>,
      provided the array's element type does not have
	new-extended alignment</ins>.<sup>224</sup></p>
    <p><em>Footnote 224:</em> It is not the direct responsibility of
	<code>operator new[]<del>(std::size_t)</del></code>
      or
	<code>operator delete[]<del>(void*)</del></code>
      to note the repetition count or element size of the array.
	Those operations are performed elsewhere in the array
	<code>new</code>
      and
	<code>delete</code>
      expressions.
	The array
	<code>new</code>
      expression, may, however,
	increase the <code>size</code> argument to
	<code>operator new[]<del>(std::size_t)</del></code>
      to obtain space to store supplemental information.</p>
    <p class="numbered">
      <em>Replaceable:</em>
      a C++ program <del>can</del> <ins>may</ins> define a
	function with this function signature
	that displaces the default version
	defined by the C++ standard library.
	<span class="ed">This should be changed
	  similarly to paragraph 2 above.</span></p>
    <p class="numbered">
      <em>Required behavior:</em>
      Same as for
	<del><code>operator new(std::size_t)</code></del>
      <ins>the corresponding single-object forms</ins>.
	This requirement is binding on a
	replacement version
	of this function.
	<span class="ed">The last sentence should be changed
	  similarly to paragraph 3 above.</span></p>
    <p class="numbered">
      <em>Default behavior:</em>
      Returns
	<code>operator new(size)</code><ins>,
	or <code>operator new(size, alignment)</code>,
	  respectively</ins>.</p>
    <p class="decl"><code>void* operator new[](std::size_t size,
		const std::nothrow_t&amp;) noexcept;<br />
      <ins>void* operator new[](std::size_t size,
		    std::align_val_t alignment,
		    const std::nothrow_t&amp;) noexcept;</ins></code></p>
    <p class="numbered">
      <em>Effects:</em>
      Same as above, except that <del>it is</del>
      <ins>these are</ins> called by a placement version of a
	<var>new-expression</var>
      when a C++ program prefers a null pointer result
	as an error indication,
	instead of a
	<code>bad_alloc</code>
      exception.</p>
    <p class="numbered">
      <em>Replaceable:</em>
      a C++ program <del>can</del> <ins>may</ins> define a
	function with this function signature
	that displaces the default version
	defined by the C++ standard library.
	<span class="ed">This should be changed
	    similarly to paragraph 2.</span></p>
    <p class="numbered">
      <em>Required behavior:</em>
      Return a non-null pointer
	to suitably aligned storage ([basic.stc.dynamic]),
	or else return a null pointer.
	<del>This</del> <ins>Each of these</ins>
      nothrow <del>version</del> <ins>versions</ins>
      of <code>operator new[]</code> returns
	a pointer obtained as if
	acquired from the (possibly replaced)
	<del><code>operator new[](std::size_t)</code> function</del>
      <ins>corresponding non-placement function</ins>.
	This requirement is binding
	on a replacement version of this function.
	<span class="ed">The last sentence should be changed
	    similarly to paragraph 3.</span></p>
    <p class="numbered">
      <em>Default behavior:</em>
      Calls <code>operator new[](size)</code><ins>,
	    or <code>operator new[](size, alignment)</code>,
	  respectively</ins>.
	If the call returns normally,
	returns the result of that call.
	Otherwise, returns a null pointer.</p>
    <p class="decl"><code>void operator delete[](void* ptr) noexcept;<br />
      void operator delete[](void* ptr,
		std::size_t size) noexcept;<br />
      <ins>void operator delete[](void* ptr,
		    std::align_val_t alignment) noexcept;<br />
	void operator delete[](void* ptr,
		    <span class="new">std::size_t size,
		    std::align_val_t alignment</span>) noexcept;</ins>
    </code></p>
    <p class="numbered">
      <em>Effects:</em>
      The deallocation <del>function</del> <ins>functions</ins> ([basic.stc.dynamic.deallocation])
	called by the array form of a
	<var>delete-expression</var>
      to render the value of <code>ptr</code> invalid.</p>
    <p class="numbered">
      <em>Replaceable:</em>
      a C++ program <del>can</del> <ins>may</ins> define
	<del>a function with signature
	<code>void operator delete[](void* ptr) noexcept</code>
	  that displaces</del>
      <ins>functions with any of these signatures,
	    and thereby displace</ins>
      the default version<ins>(s)</ins>
      defined by the C++ standard library.
	If <del>this</del> <ins>a</ins> function
	<del>(</del>without <ins>a</ins> <code>size</code>
      parameter<del>)</del> is defined,
	the program should also define
	<del><code>void operator delete[](void* ptr,
	    std::size_t size) noexcept</code></del>
      <ins>the corresponding function
	    with a <code>size</code> parameter</ins>.
	If <del>this</del> <ins>a</ins> function
	with <ins>a</ins> <code>size</code> parameter is defined,
	the program shall also define
	the <ins>corresponding</ins> version
	without the <code>size</code> parameter.
	[ <em>Note</em>: The default behavior below
	may change in the future,
	which will require replacing both deallocation functions
	when replacing the allocation function.
	&mdash;<em>end note</em> ]</p>
    <p class="numbered">
      <em>Requires:</em>
      <code>ptr</code> shall be a null pointer or its value shall
	<del>be the value returned</del>
      <ins>point to a block of memory allocated</ins>
      by an earlier call to
	<ins>a (possibly replaced)</ins>
      <code>operator new[](std::size_t)</code>
      or
	<code>operator new[](std::size_t,
	    <del>const std::nothrow_t&amp;</del> <ins>std::align_val_t</ins>)</code>
      which has not been invalidated by an intervening call to
	<code>operator delete[]<del>(void*)</del></code> <del>or
	    <code>operator delete[](void*,
	      std::size_t)</code></del>.</p>
    <p class="numbered">
      <em>Requires:</em>
      <ins>If the <code>alignment</code> parameter is not present,
	    <code>ptr</code> shall have been returned
	    by an allocation function
	    without an <code>alignment</code> parameter.
	    If present, the <code>alignment</code> argument shall equal
	    the alignment argument passed to the allocation function
	    that returned <code>ptr</code>.</ins>
      If present,
	the <code><del>std::size_t</del> size</code> argument
	<del>must</del> <ins>shall</ins> equal the size
	argument passed to the allocation function
	that returned <code>ptr</code>.</p>
    <p class="numbered">
      <em>Required behavior:</em>
      <del>Calls</del> <ins>A call</ins> to
	<code>operator delete[]<del>(void* ptr,
	    std::size_t size)</del></code>
      <ins class="new">with a <code>size</code> parameter</ins>
      may be changed to <del>calls</del> <ins>a call</ins> to
	<code>operator delete[]<del>(void* ptr)</del></code>
      <ins class="new">without a <code>size</code> parameter,</ins>
      without affecting memory allocation.
	[ <em>Note:</em> A conforming implementation is for
	<code>operator delete[](void* ptr, std::size_t size)</code>
      to simply call
	<code>operator delete[](void* ptr)</code>.
	&mdash;<em>end note</em> ]</p>
    <p class="numbered">
      <em>Requires:</em>
      If an implementation
	has strict pointer safety ([basic.stc.dynamic.safety])
	then <code>ptr</code> shall be a safely-derived pointer.</p>
    <p class="numbered">
      <em>Default behavior:</em>
      <del><code>operator delete[](void* ptr,
	    std::size_t size)</code> calls
	<code>operator delete[](ptr)</code>, and
	<code>operator delete[](void* ptr)</code> calls
	<code>operator delete(ptr)</code>.</del>
      <ins>The functions that have a <code>size</code> parameter
	    forward their other parameters
	    to the corresponding function
	    without a <code>size</code> parameter.
	    The functions that do not have
	    a <code>size</code> parameter
	    forward their parameters
	    to the corresponding <code>operator delete</code>
	(single-object) function.</ins>
    </p>
    <p class="ed">This is the one place in the standard
      where the default behavior needs to be specified
      for four replaceable functions.
      My senses of esthetics and propriety rebelled
      at the prospect of enumerating them all,
      especially in a single flowing paragraph.</p>
    <p class="decl"><code>void operator delete[](void* ptr,
		const std::nothrow_t&amp;) noexcept;<br />
      <ins>void operator delete[](void* ptr,
		    std::align_val_t alignment,
		const std::nothrow_t&amp;) noexcept;</ins>
    </code></p>
    <p class="numbered">
      <em>Effects:</em>
      The deallocation <del>function</del> <ins>functions</ins> ([basic.stc.dynamic.deallocation])
	called by the implementation
	to render the value of <code>ptr</code> invalid
	when the constructor invoked from a nothrow
	placement version of the array <var>new-expression</var>
      throws an exception.</p>
    <p class="numbered">
      <em>Replaceable:</em>
      a C++ program may define <del>a function</del> <ins>functions</ins> with <del>signature
	<code>void operator delete[](void* ptr,
	    const std::nothrow_t&amp;) noexcept</code>
	that displaces</del>
      <ins>any of these signatures, and thereby displace</ins>
      the default version<ins>(s)</ins> defined by the
	C++ standard library.</p>
    <p class="numbered new">
      <ins><em>Requires:</em>
      <code>ptr</code> shall be a null pointer or its value shall
      point to a block of memory allocated
      by an earlier call to
      a (possibly replaced)
      <code>operator new[](std::size_t)</code>
      or
	<code>operator new[](std::size_t,
	  std::align_val_t)</code>
      which has not been invalidated by an intervening call to
	<code>operator delete[]</code>.</ins></p>
    <p class="numbered new">
      <ins><em>Requires:</em>
      If the <code>alignment</code> parameter is not present,
	    <code>ptr</code> shall have been returned
	    by an allocation function
	    without an <code>alignment</code> parameter.
	    If present, the <code>alignment</code> argument shall equal
	    the alignment argument passed to the allocation function
	    that returned <code>ptr</code>.</ins></p>
    <p class="numbered">
      <em>Requires:</em>
      If an implementation
	has strict pointer safety ([basic.stc.dynamic.safety])
	then <code>ptr</code> shall be a safely-derived pointer.</p>
    <p class="numbered">
      <em>Default behavior:</em>
      <ins>The function</ins> <code>operator delete[](void* ptr,
	    const std::nothrow_t&amp;)</code>
      calls
	<code>operator delete[](ptr)</code>.
	<ins>The function <code>operator delete[](void* ptr,
		std::align_val_t alignment,
		const std::nothrow_t&amp;)</code>
	  calls
	  <code>operator delete[](ptr, alignment)</code>.</ins></p>
  </blockquote>
  <p>Change the title of section 18.6.2.3:</p>
  <blockquote>
    <h4>18.6.2.3 <del>Placement</del> <ins>Non-allocating</ins> forms
      <span class="right">[new.delete.placement]</span>
    </h4>
  </blockquote>
  <p>Change 20.9.9.1p5:</p>
  <blockquote>
    <p><em>Returns:</em>
      A pointer to the initial element of an array of storage
	of size <code>n * sizeof(T)</code>,
	aligned appropriately for objects of type <code>T</code>.
	<del>It is implementation-defined
	    whether over-aligned types are supported (3.11).</del></p>
  </blockquote>
  <p>Change 20.9.9.1p6:</p>
  <blockquote>
    <p><em>Remark:</em> the storage is obtained
      by calling <code>::operator new<del>(std::size_t)</del></code>
      (18.6.2),
      but it is unspecified when or how often
      this function is called.
      The use of <code>hint</code> is unspecified,
      but intended as an aid to locality
      if an implementation so desires.</p>
  </blockquote>
  <p>Change 20.9.9.1p10:</p>
  <blockquote>
    <p><em>Remarks:</em>
      Uses <code>::operator delete<del>(void*, std::size_t)</del></code>
      (18.6.2), but it is unspecified when this function is called.</p>
  </blockquote>
  <p>Change 20.9.11p1:</p>
  <blockquote>
    <p><em>Effects:</em>
      Obtains a pointer to uninitialized,
	contiguous storage for <em>N</em> adjacent objects
	of type <code>T</code>,
	for some non-negative number <em>N</em>.
	<del>It is implementation-defined
	  whether over-aligned types are supported (3.11).</del></p>
  </blockquote>
  <p>Add a new entry to C.4.2:</p>
  <blockquote class="new">
    <p>5.3.4, 5.3.5</p>
    <p><strong>Change:</strong>
      Dynamic allocation mechanism for over-aligned types.</p>
    <p><strong>Rationale:</strong>
      Simplify use of over-aligned types.</p>
    <p><strong>Effect on original feature:</strong>
      In C++14 code that uses a <var>new-expression </var>
      to allocate an object with an over-aligned class type,
      where that class has no allocation functions of its own,
      <code>::operator new(std::size_t)</code> is used
      to allocate the memory.
      In this International Standard,
      <code>::operator new(std::size_t, std::align_val_t)</code>
      is used instead.</p>
  </blockquote>
</body>
</html>
