<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">

<title>Not so Trivial Issues with Trivial</title>
</head>

<body>
<h1>Not so Trivial Issues with Trivial</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N2749 = 08-0259 - 2008-08-24
</p>

<p>
Lawrence Crowl, Lawrence@Crowl.org, crowl@google.com
<br>
Jens Maurer, Jens.Maurer@gmx.net
</p>


<h2>Problem</h2>

<p>
The original formulation of deleted functions
(<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2210.htm">N2210</a>)
defined
deleted special member functions to be trivial.
The intent was to not change the efficiency features
associated with trivial types
simply because use of a function is prohibited.
However, the adopted formulation
(<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2346.htm">N2346</a>)
made deleted special member functions non-trivial.
</p>

<p>
The consequence of non-trivial deleted functions
is that many desirable efficiency features defined for trivial types
no longer apply.
For example, deleting a default constructor made a class non-trivial,
which in turn no longer guaranteed static initialization.
Indeed, there is no reason that a non-deleted, non-trivial default constructor
should necessarily affect static initialization either.
The problem extends to other features,
including object lifetime, parameter passing, and <code>memcpy</code>.
</p>

<p>
The core of the problem is that
many features are defined for trivial types
when they generally rely on only a subset of the attributes
that define a trivial type.
</p>

<h2>Solution</h2>

<p>
We propose to redefine those features
that are defined with trivial types
to be defined with the set of attributes crucial to the feature.
Features already defined directly in terms of attributes
need no change.
This proposal is a continuation in the work of decomposing POD types
and their features
that began with
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2007/n2342.htm">N2342
POD's Revisited; Resolving Core Issue 568 (Revision 5)</a>.
</p>

<p>
In our solution,
we introduce the notion of a trivially copyable type.
We then apply this notion in several places.
We have chosen a conservative definition for trivally copyable;
at lease one weaker form exists.
</p>

<p>
With the introduction of trivally copyable types,
and the redefinition of features on type attributes,
there are very few remaining uses of trivial types in the standard.
We recommend that any new uses be very carefully considered
and weaker types are likely to be preferable.
</p>

<p>
Several core-language issues are closely related.
A full resolution of the problems requires resolving these issues as well.
That work is in progress.
</p>
<ul>
<li>
509. Dead code in the specification of default initialization
</li>
<li>
684. Constant expressions involving the address of an automatic variable
</li>
<li>
688. Constexpr constructors and static initialization
</li>
</ul>


<h2>Wording</h2>

<p>
The wording in this paper includes unmodified paragraphs.
These paragraphs serve to provide context for the changes proposed.
We anticipate that a revision for formal voting
will remove those unmodified paragraphs.
</p>


<h3>1.8 The C++ object model [intro.object]</h3>

<p>
Edit paragraph 5 as follows.
</p>

<blockquote>
<p>
An object of <del>trivial</del> <ins>trivially copyable</ins>
or standard-layout type (3.9)
shall occupy contiguous bytes of storage.
</p>
</blockquote>


<h3>3.6.2 Initialization of non-local objects [basic.start.init]</h3>

<p>
Paragraph 1 will be modified by issue 688 to avoid the term "trivial".
Issue 684 may also affect this paragraph.
</p>

<blockquote>
<p>
Objects with static storage duration (3.7.1)
shall be zero-initialized (8.5) before any other initialization takes place.
A reference with static storage duration
and an object of trivial or literal type with static storage duration
can be initialized with a constant expression (5.19 [expr.const]);
this is called <dfn>constant initialization</dfn>.
...
</p>
</blockquote>


<h3>3.8 Object Lifetime [basic.life]</h3>

<p>
Leave paragraph 1 unchanged.
</p>

<blockquote>
<p>
The <dfn>lifetime</dfn> of an object is a runtime property of the object.
The lifetime of an object of type <code>T</code> begins when:
</p>

<ul>
<li>
storage with the proper alignment and size for type <code>T</code> is obtained, and
</li>

<li>
if <code>T</code> is a class type
and the constructor invoked to create the object is non-trivial (12.1),
the principal constructor call (12.6.2) has completed.
[<i>Note:</i>
the initialization can be performed by a constructor call
or, in the case of an aggregate
with an implicitly-declared non-trivial default constructor,
an aggregate initialization 8.5.1.
&mdash;<i>end note</i>]
</li>
</ul>

<p>
The lifetime of an object of type T ends when:
</p>

<ul>
<li>
if <code>T</code> is a class type with a non-trivial destructor (12.4),
the destructor call starts, or
</li>
<li>
the storage which the object occupies is reused or released.
</li>
</ul>
</blockquote>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote>
<p>
[<i>Note:</i>
the lifetime of an array object
or of an object of <del>trivial type (3.9)</del>
<ins>scalar type or of class type with a trivial default constructor</ins>
starts as soon as storage with proper size and alignment is obtained<del>,
and its</del><ins>.
The</ins> lifetime <ins>of an array object
or of an object of scalar type or of class type with a trivial destructor</ins>
ends when the storage which the array or object occupies
is reused or released.
12.6.2 describes the lifetime of base and member subobjects.
&mdash;<i>end note</i>]
</p>
</blockquote>

<p>
Leave paragraph 4 unchanged.
</p>
<blockquote>
<p>
A program may end the lifetime of any object
by reusing the storage which the object occupies
or by explicitly calling the destructor
for an object of a class type with a non-trivial destructor.
For an object of a class type with a non-trivial destructor,
the program is not required to call the destructor explicitly
before the storage which the object occupies is reused or released;
however, if there is no explicit call to the destructor
or if a delete-expression (5.3.5) is not used to release the storage,
the destructor shall not be implicitly called
and any program that depends on the side effects
produced by the destructor has undefined behavior.
</p>
</blockquote>

<p>
Edit paragraph 5 as follows.
</p>

<blockquote>
<p>
Before the lifetime of an object has started
but after the storage which the object will occupy
has been allocated<sup>35)</sup> or,
after the lifetime of an object has ended
and before the storage which the object occupied is reused or released,
any pointer that refers to the storage location
where the object will be or was located
may be used but only in limited ways.
Such a pointer refers to allocated storage (3.7.3.2),
and using the pointer as if the pointer were of type <code>void*</code>,
is well-defined.
Such a pointer may be dereferenced
but the resulting lvalue may only be used in limited ways,
as described below.
If the object will be or was of a class type with a non-trivial destructor,
and the pointer is used as the operand of a <var>delete-expression</var>,
the program has undefined behavior.
If the object will be or was of a <del>non-trivial</del> class type
<ins>with virtual bases or virtual member functions</ins>,
the program has undefined behavior if:
</p>
<ul>
<li>
the pointer is used to access a non-static data member
or call a non-static member function of the object,
or
</li>
<li>
the pointer is implicitly converted (4.10) to a pointer to a base class type,
or
</li>
<li>
the pointer is used as the operand of a <code>static_cast</code> (5.2.9)
(except when the conversion is to <code>void*</code>, or to <code>void*</code>
and subsequently to <code>char*</code>, or <code>unsigned char*</code>).
</li>
<li>....</li>
</ul>
</blockquote>

<p>
Edit paragraph 6 as follows.
</p>

<blockquote>
<p>
Similarly, before the lifetime of an object has started
but after the storage which the object will occupy has been allocated or,
after the lifetime of an object has ended
and before the storage which the object occupied is reused or released,
any lvalue which refers to the original object may be used
but only in limited ways.
Such an lvalue refers to allocated storage (3.7.3.2),
and using the properties of the lvalue
which do not depend on its value is well-defined.
If an lvalue-to-rvalue conversion (4.1) is applied to such an lvalue,
the program has undefined behavior;
if the original object will be or was of a <del>non-trivial</del> class type
<ins>with virtual bases or virtual member functions</ins>,
the program has undefined behavior if:
</p>
<ul>
<li>
the lvalue is used to access a non-static data member
or call a non-static member function of the object, or
</li>
<li>
the lvalue is implicitly converted (4.10) to a reference to a base class type,
or
</li>
<li>
the lvalue is used as the operand of a <code>static_cast</code> (5.2.9)
except when the conversion
is ultimately to <var>cv</var> <code>char&amp;</code>
or <var>cv</var> <code>unsigned char&amp;</code>, or
</li>
<li>
the lvalue is used as the operand of a <code>dynamic_cast</code> (5.2.7)
or as the operand of typeid.
</li>
</ul>
</blockquote>

<p>
Leave paragraph 8 unchanged.
</p>

<blockquote>
<p>
If a program ends the lifetime of an object of type <code>T</code>
with static (3.7.1) or automatic (3.7.2) storage duration
and if <code>T</code> has a non-trivial destructor,<sup>36)</sup>
the program must ensure that an object of the original type
occupies that same storage location
when the implicit destructor call takes place;
otherwise the behavior of the program is undefined.
This is true even if the block is exited with an exception.
</p>
</blockquote>


<h3>3.9 Types [basic.types]</h3>

<p>
Edit paragraph 2 as follows:
</p>

<blockquote>
<p>
For any object (other than a base-class subobject)
of <del>trivial</del> <ins>trivially copyable</ins> type <code>T</code>,
whether or not the object holds a valid value of type <code>T</code>,
the underlying bytes (1.7) making up the object
can be copied into an array of char or unsigned char.<sup>36)</sup>
If the content of the array of char or unsigned char
is copied back into the object,
the object shall subsequently hold its original value.
</p>
</blockquote>

<p>
Edit paragraph 3 as follows:
</p>

<blockquote>
<p>
For any <del>trivial</del> <ins>trivially copyable</ins> type <code>T</code>,
if two pointers to <code>T</code>
point to distinct <code>T</code> objects
<code>obj1</code> and <code>obj2</code>,
where neither <code>obj1</code> nor <code>obj2</code> is a base-class subobject,
if the value of <code>obj1</code> is copied into <code>obj2</code>,
using the <code>std::memcpy</code> library function,
<code>obj2</code> shall subsequently hold the same value as <code>obj1</code>.
[<i>Example:</i>
</p>
<pre>
<code>T* t1p;</code>
<code>T* t2p;</code>
<em>// provided that <code>t2p</code> points to an initialized object ...</em>
<code>std::memcpy(t1p, t2p, sizeof(T));</code>
<em>// at this point, every subobject of <del>trivial</del> <ins>trivially copyable</ins> type in <code>*t1p</code> contains</em>
<em>// the same value as the corresponding subobject in <code>*t2p</code></em>
</pre>
<p>
&mdash;<i>end example</i>]
</p>
</blockquote>

<p>
Edit paragraph 4 as follows:
</p>

<blockquote>
<p>
The <dfn>object representation</dfn> of an object of type <code>T</code>
is the sequence of <code>N unsigned char</code> objects
taken up by the object of type <code>T</code>,
where <code>N</code> equals <code>sizeof(T)</code>.
The value representation of an object
is the set of bits that hold the value of type <code>T</code>.
For <del>trivial</del>
<ins>trivially copyable</ins> types,
the value representation is a set of bits in the object representation
that determines a value,
which is one discrete element of an implementation-defined set of values.
[<i>Footnote:</i>
The intent is that the memory model of C++
is compatible with that of ISO/IEC 9899 Programming Language C.
&mdash;<i>end footnote</i>]
</p>
</blockquote>

<p>
Edit paragraph 9 as follows.
</p>

<blockquote>
<p>
Arithmetic types (3.9.1), enumeration types, pointer types,
pointer to member types (3.9.2), and <code>std::nullptr_t</code>,
and <var>cv-qualified</var> versions of these types (3.9.3)
are collectively called <dfn>scalar types</dfn>.
Scalar types, POD classes (clause 9), arrays of such types
and <var>cv-qualified</var> versions of these types (3.9.3)
are collectively called <dfn>POD types</dfn>.
<ins>Scalar types, trivially copyable class types (clause 9),
arrays of such types
and cv-qualified versions of these types (3.9.3)
are collectively called <dfn>trivially copyable types</dfn>.</ins>
Scalar types, trivial class types (clause 9),
arrays of such types
and cv-qualified versions of these types (3.9.3)
are collectively called <dfn>trivial types</dfn>.
Scalar types, standard-layout class types (clause 9),
arrays of such types
and cv-qualified versions of these types (3.9.3)
are collectively called <dfn>standard-layout types</dfn>.
</p>
</blockquote>

<p>
Leave paragraph 10 unchanged.
</p>

<blockquote>
<p>
A type is a literal type if it is:
</p>

<ul>
<li>
a scalar type; or
</li>

<li>
a class type (clause 9) with
<ul>
<li>a trivial copy constructor,</li>
<li>a trivial destructor,</li>
<li>a trivial default constructor or
at least one constexpr constructor other than the copy constructor, and</li>
<li>all non-static data members and base classes of literal types; or</li>
<li>an array of literal type.</li>
</ul>
</li>
</ul>
</blockquote>


<h3>5.2.2 Function call [expr.call]</h3>

<p>
Edit paragraph 7 as follows.
</p>

<blockquote>
<p>
...
Passing an argument of <del>non-trivial</del> class type (clause 9)
<ins>with a non-trivial copy constructor or a non-trivial destructor</ins>
with no corresponding parameter
is conditionally-supported,
with implementation-defined semantics.
...
</p>
</blockquote>


<h3>5.3.4 New [expr.new]</h3>

<p>
Paragraph 16 will be modified by issue 509 to avoid the term "trivial".
</p>

<blockquote>
<p>
A <dfn>new-expression</dfn>
that creates an object of type <code>T</code>
initializes that object as follows:
</p>
<ul>
<li>If the <var>new-initializer</var> is omitted:
<ul>
<li>
If <code>T</code> is a (possibly cv-qualified)
non-trivial class type (or array thereof),
the object is default-initialized (8.5).
If <code>T</code> is a const-qualified type,
the underlying class type shall have a user-provided default constructor.
</li>
<li>
Otherwise, the object created has indeterminate value.
If <code>T</code> is a const-qualified type,
or a (possibly cv-qualified) trivial class type (or array thereof)
containing (directly or indirectly) a member of const-qualified type,
the program is ill-formed;
</li>
</ul>
</li>
<li>...</li>
</ul>
</blockquote>


<h3>5.3.5 Delete [expr.delete]</h3>

<p>
Leave paragraph 5 unchanged.
</p>

<blockquote>
<p>
If the object being deleted has incomplete class type at the point of deletion
and the complete class has a non-trivial destructor or a deallocation function,
the behavior is undefined.
</p>
</blockquote>


<h3>5.19 Constant expressions [expr.const]</h3>

<p>
Edit paragraph 2 as follows.
Note that issue 684 will make non-conflicting edits to this paragraph.
</p>

<blockquote>
<p>
A <dfn>conditional-expression</dfn> is a constant expression
unless it involves one of the following
as a potentially evaluated subexpression (3.2),
but subexpressions of
logical AND (5.14), logical OR (5.15), and conditional (5.16) operations
that are not evaluated are not considered
[<i>Note:</i>
an overloaded operator invokes a function
&mdash;<i>end note</i>]:
</p>

<ul>
<li>...</li>
<li>
a class member access (5.2.5)
unless its postfix-expression is of <del>trivial or</del> literal type
or of pointer to <del>trivial or</del> literal type;
</li>
<li>...</li>
</ul>
</blockquote>


<h3>6.7 Declaration statement [stmt.dcl]</h3>

<p>
Edit paragraph 3 as follows:
</p>

<blockquote>
<p>
It is possible to transfer into a block,
but not in a way that bypasses declarations with initialization.
A program that jumps<sup>78)</sup>
from a point where a local variable with automatic storage duration
is not in scope
to a point where it is in scope
is ill-formed unless the variable has <del>trivial type (3.9)</del>
<ins>a trivial default constructor and a trivial destructor</ins>
and is declared without an <var>initializer</var> (8.5).
</p>
</blockquote>

<p>
Paragraph 4 will be modified by issue 688 to avoid the term "trivial".
</p>

<blockquote>
<p>
The zero-initialization (8.5)
of all local objects with static storage duration (3.7.1)
is performed before any other initialization takes place.
A local object of trivial or literal type (3.9 [basic.types])
with static storage duration initialized with <var>constant-expression</var>s
is initialized
before its block is first entered
An implementation is permitted to perform early initialization
of other local objects with static storage duration
under the same conditions
that an implementation is permitted to statically initialize an object
with static storage duration in namespace scope (3.6.2).
Otherwise such an object is initialized
the first time control passes through its declaration;
such an object is considered initialized
upon the completion of its initialization.
If the initialization exits by throwing an exception,
the initialization is not complete,
so it will be tried again the next time control enters the declaration.
If control re-enters the declaration (recursively)
while the object is being initialized,
the behavior is undefined.
</p>
</blockquote>


<h3>7.1.5 The <code>constexpr</code> specifier [dcl.constexpr]</h3>

<p>
Leave paragraph 4 unchanged.
</p>

<blockquote>
<p>
A trivial copy constructor is also a constexpr constructor.
</p>
</blockquote>

<p>
Paragraph 7 will be modified by issue 688.
</p>

<blockquote>
<p>
A <code>constexpr</code> specifier used in an object declaration
declares the object as <code>const</code>.
Such an object shall be initialized,
and every expression that appears in its initializer (8.5 [dcl.init])
shall be a constant expression.
Every implicit conversion used in converting the initializer expressions
and every constructor call used for the initialization
shall be one of those allowed in a constant expression (5.19 [expr.const])
...
</p>
</blockquote>


<h3>8.4 Function definitions [dcl.fct.def]</h3>

<p>
Leave paragraph 9 unchanged.
</p>

<blockquote>
<p>
...
A special member function is user-provided if it is user-declared
and not explicitly defaulted on its first declaration.
...
</p>

<pre><code>
struct trivial {
  trivial() = default;
  trivial(const trivial&amp;) = default;
  trivial&amp; operator =(const trivial&amp;) = default;
  ~trivial() = default;
};
</code></pre>
<p>
...
</p>
</blockquote>


<h3>8.5 Initializers [dcl.init]</h3>

<p>
Edit paragraph 5 as follows.
This paragraph will also be modified by issue 509.
</p>

<blockquote>
<p>
To default-initialize an object of type <code>T</code> means:
</p>
<ul>
<li>
if <code>T</code> is a <del>non-trivial</del> class type (clause 9),
the default constructor for <code>T</code> is called
(and the initialization is ill-formed
if <code>T</code> has no accessible default constructor);
</li>
</ul>
</blockquote>

<p>
Edit paragraph 9 as follows.
This paragraph will also be modified by issue 509.
</p>

<blockquote>
<p>
If no initializer is specified for an object,
and the object <del>is of (possibly cv-qualified) non-trivial class type
(or array thereof)</del>
<ins>has a non-trivial default constructor</ins>,
the object shall be default-initialized;
if the object is of const-qualified type,
the underlying class type shall have a user-provided default constructor.
Otherwise, if no initializer is specified for a non-static object,
the object and its subobjects, if any,
have an indeterminate initial value<sup>95)</sup>;
if the object or any of its subobjects are of const-qualified type,
the program is ill-formed.
</p>
</blockquote>


<h3>8.5.1 Aggregates [dcl.init.aggr]</h3>

<p>
Paragraph 14 will be heavily modified by issue 688
and thus avoid the term "trivial".
</p>

<blockquote>
<p>
When an aggregate with static storage duration
is initialized with a brace-enclosed <var>initializer-list</var>,
if all the member initializer expressions are constant expressions,
and the aggregate is a trivial type,
the initialization shall be done
during the static phase of initialization (3.6.2 [basic.start.init]);
otherwise, it is unspecified
whether the initialization of members with constant expressions
takes place during the static phase
or during the dynamic phase of initialization.
</p>
</blockquote>


<h3>Chapter 9 Classes [class]</h3>

<p>
Edit paragraph 5 as follows.
</p>

<blockquote>
<p>
<ins>A trivially copyable class is a class that:</ins>
</p>
<ul>
<li><ins>has a trivial copy constructor (12.8),</ins></li>
<li><ins>has a trivial copy assignment operator (13.5.3, 12.8), and</ins></li>
<li><ins>has a trivial destructor (12.4).</ins></li>
</ul>
<p>
A trivial class is a class that:
</p>
<ul>
<li>has a trivial default constructor (12.1),
<ins>and</ins></li>
<li><del>has a trivial copy constructor (12.8),</del></li>
<li><del>has a trivial copy assignment operator (13.5.3, 12.8), and</del></li>
<li><del>has a trivial destructor (12.4).</del></li>
<li><ins>is trivially copyable.</ins></li>
</ul>
<p>
[<i>Note:</i>
in particular, a <ins>trivially copyable or </ins> trivial class
does not have virtual functions or virtual base classes.
&mdash;<i>end note</i>]
</p>
</blockquote>

<p>
Leave paragraph 9 unchanged.
</p>

<blockquote>
<p>
A <dfn>POD struct</dfn> is a class
that is both a trivial class and a standard-layout class,
and has no non-static data members of type non-POD struct,
non-POD union (or array of such types).
Similarly, a <dfn>POD union</dfn> is a union
that is both a trivial class and a standard layout class,
and has no non-static data members of type non-POD struct,
non-POD union (or array of such types).
A <dfn>POD class</dfn> is a class that is either a POD struct or a POD union.
</p>
</blockquote>


<h3>9.5 Unions [class.union]</h3>

<p>
Within paragraph 1 edit as follows.
</p>

<blockquote>
<p>
...
[<i>Note:</i>
If any non-static data member of a union
has a non-trivial default constructor (12.1),
copy constructor (12.8), copy assignment operator (12.8), or destructor (12.4),
the corresponding member function of the union must be
<del>user-declared</del> <ins>user-provided</ins>
or it will be implicitly deleted (8.4) for the union. 
&mdash;<i>end note</i>]
</p>
</blockquote>


<h3>12.1 Constructors [class.ctor]</h3>

<p>
Leave paragraph 5 unchanged.
</p>

<blockquote>
<p>
A <dfn>default</dfn> constructor for a class <code>X</code>
is a constructor of class <code>X</code>
that can be called without an argument.
If there is no user-declared constructor for class <code>X</code>,
a default constructor having no parameters is implicitly declared.
An implicitly-declared default constructor
is an <code>inline public</code> member of its class.
For a union-like class
that has a variant member with a non-trivial default constructor,
an implicitly-declared default constructor is defined as deleted (8.4).
A default constructor is <dfn>trivial</dfn>
if it is not user-provided (8.4) and if:
</p>
<ul>
<li>
its class has no virtual functions (10.3)
and no virtual base classes (10.1), and
</li>

<li>
all the direct base classes of its class have trivial default constructors, and
</li>

<li>
for all the non-static data members of its class
that are of class type (or array thereof),
each such class has a trivial default constructor.
</li>
</ul>
</blockquote>


<h3>12.2 Temporary objects [class.temporary]</h3>

<p>
Leave paragraph 3 unchanged.
</p>

<blockquote>
<p>
When an implementation introduces a temporary object
of a class that has a non-trivial constructor (12.1, 12.8),
it shall ensure that a constructor is called for the temporary object.
Similarly, the destructor shall be called
for a temporary with a non-trivial destructor (12.4).
Temporary objects are destroyed
as the last step in evaluating the full-expression (1.9)
that (lexically) contains the point where they were created.
This is true even if that evaluation ends in throwing an exception.
The value computations and side effects of destroying a temporary object
are associated only with the full-expression,
not with any specific subexpression.
</p>
</blockquote>


<h3>12.4 Destructors [class.dtor]</h3>

<p>
Edit paragraph 3 as follows.
</p>

<blockquote>
<p>
If a class has no user-declared destructor,
a destructor is declared implicitly.
An implicitly-declared destructor
is an <code>inline public</code> member of its class.
If the class is a union-like class
that has a variant member with a non-trivial destructor,
an implicitly-declared destructor is defined as deleted (8.4).
A destructor is trivial if it is not user-provided and if:
</p>

<ul>
<li>
<ins>the destructor is not <code>virtual</code>,</ins>
</li>

<li>
all of the direct base classes of its class
have trivial destructors<ins>,</ins> and
</li>

<li>
for all of the non-static data members of its class
that are of class type (or array thereof),
each such class has a trivial destructor.
</li>
</ul>
</blockquote>


<h3>12.6.2 Initializing bases and members [class.base.init]</h3>

<p>
Paragraph 4 will be modified by issue 509 to avoid use of "trivial".
</p>

<blockquote>
<p>
If a given non-static data member or base class
is not named by a mem-initializer-id
(including the case where there is no mem-initializer-list
because the constructor has no ctor-initializer),
then
</p>

<ul>
<li>
If the entity is a non-static non-variant data member
of (possibly cv-qualified) class type (or array thereof)
or a base class, and the entity class is a non-trivial class,
the entity is default-initialized (8.5).
If the entity is a non-static data member of a const-qualified type,
the entity class shall have a user-provided default constructor.
</li>

<li>
Otherwise, the entity is not initialized. If the entity is
of const-qualified type or reference type, or of a (possibly
cv-qualified) trivial class type (or array thereof) containing
(directly or indirectly) a member of a const-qualified type,
the program is ill-formed.
</li>
</ul>

<p>
an implicitly-declared copy constructor is defined as deleted (8.4).
</p>
</blockquote>


<h3>12.7 Construction and destruction [class.cdtor]</h3>

<p>
Edit paragraph 1 as follows.
</p>

<blockquote>
<p>
<del>For an object of non-trivial class type (clause 9),
before the constructor begins execution
and after the destructor finishes execution,
referring to any non-static member or base class of the object
results in undefined behavior.</del>
<ins>For an object with a non-trivial constructor,
referring to any non-static member or base class of the object
before constructor begins
results in undefined behavior.
For an object with a non-trivial destructor,
referring to any non-static member or base class of the object
after the destructor finishes execution
results in undefined behavior.</ins>
</p>
</blockquote>


<h3>12.8 Copying class objects [class.copy]</h3>

<p>
Leave paragraph 4 unchanged.
</p>

<blockquote>
<p>
If the class definition does not explicitly declare a copy constructor,
one is declared <em>implicitly</em>.
If the class is a union-like class
that has a variant member with a non-trivial copy constructor,
an implicitly-declared copy constructor is defined as deleted (8.4).
Thus, for the class definition
...
</p>
</blockquote>

<p>
Leave paragraph 6 unchanged.
</p>

<blockquote>
<p>
A copy constructor for class <code>X</code> is trivial
if it is not user-provided (8.4) and if
</p>

<ul>
<li>
class <code>X</code> has no virtual functions (10.3)
and no virtual base classes (10.1), and
</li>

<li>
each direct base class of <code>X</code> has a trivial copy constructor, and
</li>

<li>
for all the non-static data members of <code>X</code>
that are of class type (or array thereof),
each such class type has a trivial copy constructor;
</li>
</ul>

<p>
otherwise the copy constructor is non-trivial.
</p>
</blockquote>

<p>
Leave paragraph 10 unchanged.
</p>

<blockquote>
<p>
If the class definition does not explicitly declare a copy assignment operator,
one is declared implicitly.
If the class is a union-like class
that has a variant member
with a non-trivial copy assignment operator,
an implicitly-declared copy assignment operator
is defined as deleted (8.4).
The implicitly-declared copy assignment operator for a class <code>X</code>
will have the form
...
</p>
</blockquote>

<p>
Leave paragraph 11 unchanged.
</p>

<blockquote>
<p>
A copy assignment operator for class <code>X</code> is <em>trivial</em>
if it is not user-provided and if
</p>

<ul>
<li>
class <code>X</code> has no virtual functions (10.3)
and no virtual base classes (10.1), and
</li>

<li>
each direct base class of <code>X</code>
has a trivial copy assignment operator, and
</li>

<li>
for all the non-static data members of <code>X</code>
that are of class type (or array thereof),
each such class type has a trivial copy assignment operator;
</li>
</ul>

<p>
otherwise the copy assignment operator is non-trivial.
</p>
</blockquote>


<h3>20.5.2 Header <code>&lt;type_traits&gt;</code> synopsis [meta.type.synop]</h3>

<p>
The <code>is_trivial</code> and <code>has_trivial_</code>* traits
are unchanged.
</p>


<h3>20.6.17 Class template <code>reference_closure</code> [func.referenceclosure]</h3>

<p>
Leave paragraph 3 unchanged.
</p>

<blockquote>
<p>
The instances of <code>reference_closure</code> class template
are trivial and standard-layout classes (3.9).
</p>
</blockquote>


<h3>25.4 C library algorithms [alg.c.library]</h3>

<p>
Leave paragraph 4 unchanged.
It makes <code>qsort</code> undefined if the type is not trivial.
</p>


<h3>Chapter 29 Atomic operations library [atomics]</h3>

<p>
Chapter 29 was the original motivation for this propsal.
With the proposed changes in the core language,
no change is needed in this chapter.
</p>

</body>
</html>
