<html>
<head>
<title>Requirements on programs and backwards compatibility</title>
</head>

<body>
N2693 = 08-0203<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
2008-06-28

<h1>Requirements on programs and backwards compatibility</h1>

<h2>Introduction</h2>

<p>
During the last WG21 meetings, a number of features have been moved to
the working draft that silently impose undefined behavior onto a
significant number of existing programs.  This paper proposes that
freedom be given to implementers to provide users with the option to
disable one or more of these features globally, while remaining a
conforming implementation (1.4 intro.compliance) even with those
features turned off.
</p>

<h2>Motivation</h2>

<p>
The next revision of C++, called C++0x, is announced to be a major
revision with a lot of new features.  It is well-understood that some
of these features will turn existing programs that are well-formed and
well-defined under the rules of C++03 into ill-formed ones under the
rules of C++0x.  For example, any program that uses one of the new
C++0x keywords such as "thread_local" or "alignof" is in that
category.  An upcoming core issue that removes the long-deprecated
conversion from string literals to non-const <code>char *</code> puts
some more programs into that category.  Such changes, while in some
cases burdensome when porting programs to C++0x, are diagnosed and
thus do not lead to surprising runtime failures.</p>

<p>
The situation is much different with subtle changes to the C++ object
and sequencing models, because these changes are often not diagnosable and
thus may lead to silent changes in runtime behavior compared to C++03.
Visibility of such changes to user programs may depend on the presence
or absence of sophisticated compiler optimizations and thus are an
impediment to portable programs, the primary reason for having a
standard for C++ in the first place.
The C++ standards committee should therefore avoid such silent
changes.</p>



<h2>Threading Support</h2>

<p>
The introduction of multi-threading caused a large-scale update of the
C++ sequencing and object models that, in general, tightened the
rules such that existing (by definition, single-threaded) applications
are unaffected.</p>

<p>However, the changes proposed in N2660 "Dynamic Initialization and
Destruction with Concurrency" would have had the effect of permitting
parallelization of initialization in different translation units even
for existing single-threaded programs, had there not a condition "if a
program starts a thread" been introduced at the last minute.</p>

<p>While at first sight sufficient, this condition is of little help
in the real world.  If an old, single-threaded program uses some
library and that library is upgraded to a C++0x-aware version, and the
upgraded library then starts a thread (for whatever reason) in a
dynamic initialization of one of its variables with static storage
duration, the dynamic initialization of the unsuspecting application's
global variables can now be parallelized, if in different translation
units.  It is obvious that parallel execution of application code that
wasn't prepared accordingly is unlikely to work correctly.  In this
case, some might argue that it is the library's fault to have
introduced such atrocities to the program's environment, but it is
nonetheless a silent change in behavior that would have been much
easier to debug had it been diagnosed.</p>

<p>Section 1.10p1 [intro.multithread] says</p>
<blockquote>
... Under a freestanding implementation, it is implementation-defined
whether a program can have more than one thread of execution.
</blockquote>
<p>However, there is no corresponding provision in clause 30 [threads]
that specifies which library interfaces are present in a freestanding
implementation that lacks thread support.  Further, even after the
application of N2678 "Error Handling Specification for Chapter 30
(Threads)", it is not clear which (if any) error is signalled if a
thread is created in a freestanding implementation that lacks thread
support.</p>

<p>This paper therefore proposes to introduce a feature-test
preprocessor macro and adjust clause 30 for the absence of threads.</p>


<h2>Garbage Collection Support</h2>

<p>The situation with garbage collection is much more blunt: With
C++0x, a program that uses a non-safely-derived pointer has undefined
behavior.  Embedded programs that employ extreme measures for saving
memory such as using the XOR trick for doubly-linked lists will have
undefined behavior once compiled with a C++0x compiler.</p>

<p>The library function <code>get_pointer_safety()</code> is
underspecified at best and might even be considered contradictory with
the core language wording.  In particular,</p>
<ul>
<li>"Returns pointer_safety::relaxed if pointers that are not safely
derived will be treated the same as pointers that are safely derived
for the duration of the program.": This appears to modify core
language wording in 3.7.3.3 that unambiguously states that the use of
non-safely-derived pointers is undefined behavior.  So what is it?
Undefined behavior?  Or defined behavior under certain (which?)
circumstances?</li>
<li>"Returns pointer_safety::preferred if pointers that are not safely
derived will be treated the same as pointers that are safely derived
for the duration of the program but allows the implementation to hint
that it could be desirable to avoid dereferencing pointers that are
not safely derived as described in 3.7.3.3.": What is the normative
requirement in this sentence?  If there is none, shouldn't that case
just be implementation-defined, with a footnote explaining the
"implementation hint" intention?</li>
<li>"Returns pointer_safety::strict if pointers that are not safely derived might
be treated differently than pointers that are safely derived." is a
vacuous statement at best: The core wording in 3.7.3.3 unambiguously
states that all the guarantees in the standard for pointers only apply
as long as the pointer value is safely-derived, otherwise the program
has undefined behavior, so this case is implicit in the core
wording.</li>
</ul>

<p>Requiring that programs include two implementations of their data
structures in their binary (one using safely-derived pointers, the
other one saving space by employing non-safely-derived pointers),
because garbage collection restrictions that are in force can only be
detected at runtime seems overly burdensome for resource-limited
environments; flash memory for storing program images is
expensive.</p>

<p>This paper therefore proposes to make garbage collection support
conditionally-supported at least in a freestanding environment, with
an associated feature-test preprocessor macro.</p>



<h2>Proposed Wording Changes</h2>

Change in 3.6.2 basic.start.init paragraph 1 (see N2660: Dynamic
Initialization and Destruction with Concurrency):

<blockquote>
If a program <ins>can have more than one thread of execution (1.10
intro.multithread, 18.4 support.start.term) and if it</ins> starts a
thread (30.2 [thread.threads]), the subsequent initialization of an object is
unsequenced with respect to the initialization of an object defined in
a different translation unit.
</blockquote>

Change in 3.7.3.3 basic.stc.dynamic.safety paragraph 4 (see N2670:
Minimal Support for Garbage Collection and Reachability-Based Leak
Detection (revised)):

<blockquote>
<ins>An implementation may have <em>relaxed pointer safety</em>, in
which case the validity of a pointer value does not depend on whether
it is a safely-derived pointer value or not.  Alternatively, an
implementation may have <em>strict pointer safety</em>, in which case
if</ins>
<del>If</del> a pointer value that is not a safely-derived pointer value is
dereferenced or deallocated, and the referenced complete object is of
dynamic storage duration and has not previously been declared
reachable ([util.declare_reachable]), the behavior is undefined. [
Note: This is true even if the unsafely-derived pointer value might
compare equal to some safely-derived pointer value. -- end note ]
<ins>It is implementation-defined whether an implementation has
relaxed or strict pointer safety.</ins>
</blockquote>

Add a new paragraph 4 at the end of 17.4.1.3 compliance:
<blockquote>
The header <code>&lt;thread></code> shall be present if and only if a
program can have more than one thread of execution (1.10
intro.multithread).
</blockquote>

Add two new paragraphs 13+14 at the end of 18.4 support.start.term:
<blockquote>
<p>
<code>__STDCPP_THREADS</code><br/>
The macro <code>__STDCPP_THREADS</code> shall be defined if and only
if a program can have more than one thread of execution (1.10
intro.multithread).  If the macro is defined, it shall have the same value as
the predefined macro <code>__cplusplus</code> (16.8 cpp.predefined).
[ Footnote: With this facility, an application or library can make the
implementation issue a diagnostic if it cannot operate in a
multi-threaded environment, see 3.6.2 basic.start.init. ]
</p>

<p>
<code>__STDCPP_STRICT_POINTER_SAFETY</code><br/>
The macro <code>__STDCPP_STRICT_POINTER_SAFETY</code> shall be defined
if and only if the implementation has strict pointer safety (3.7.3.3).
If the macro is defined, it shall have the same value as the
predefined macro
<code>__cplusplus</code> (16.8 cpp.predefined).  [ Footnote: With this
facility, a program can make the implementation issue
a diagnostic if the program requires relaxed pointer safety. ]
</p>
</blockquote>

In 20.6.8, replace the description of get_pointer_safety (see N2670:
Minimal Support for Garbage Collection and Reachability-Based Leak
Detection (revised)) by

<blockquote>
<pre>pointer_safety get_pointer_safety()</pre>

<p>Returns:  Returns <code>pointer_safety::strict</code> if
the implementation has strict pointer safety (3.7.3.3).
It is implementation-defined whether
<code>get_pointer_safety</code> returns <code>pointer_safety::relaxed</code> or
<code>pointer_safety::preferred</code> if the implementation has
relaxed pointer safety (3.7.3.3) [ Footnote:
<code>pointer_safety::preferred</code>
might be returned to indicate to the program that a leak detector is
running so that the program can avoid spurious leak reports.
-- end footnote ]. 
</p>

<p>
Throws:
    nothing
</p>

</blockquote>

</body>
</html>

