OSDN Git Service

2003-11-12 Benjamin Kosnik <bkoz@redhat.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Nov 2003 00:25:23 +0000 (00:25 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 13 Nov 2003 00:25:23 +0000 (00:25 +0000)
* docs/html/debug_mode.html: Update.
* docs/html/17_intro/TODO: Update.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73525 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/docs/html/17_intro/TODO
libstdc++-v3/docs/html/debug_mode.html

index c833d7b..8329b33 100644 (file)
@@ -1,5 +1,10 @@
 2003-11-12  Benjamin Kosnik  <bkoz@redhat.com>
 
+       * docs/html/debug_mode.html: Update.
+       * docs/html/17_intro/TODO: Update.
+
+2003-11-12  Benjamin Kosnik  <bkoz@redhat.com>
+
        * include/bits/c++config: Move using directive...
        * include/debug/formatter.h: ...here.
 
index 97ce333..1670f04 100644 (file)
@@ -36,12 +36,18 @@ std::locale
     functions and and LANG environment variable dependencies.
 
   - use localedata to implement generic named (non-MT-safe) locales?
-    Figure out a way to use ICU data, like libjava? Need a generic locale
-    model that does something besides the "C" locale.
+    Figure out a way to use ICU data, like libjava? Re-package and use
+    the glibc localedata, even if we aren't on linux? Need a generic
+    locale model that does something besides the "C" locale.
 
   - make locale::classic() separate from named locale code. This will
     improve the static linkage situation, but will require new
-    initialization code.
+    initialization code. In particular, we need lazy-initialization of
+    locale::classic(), and maybe the has_facet/use_facet functions for all
+    the required facets. The end goal is a self-contained
+    locale_init.cc, or one with transitive closure without the locale
+    instantiations (locale-inst.cc) or the named locale bits
+    (localename.cc).
 
   - Jerry(?)/Paolo(?) work on __float_to_char.
 
@@ -52,9 +58,9 @@ std::locale
 std::basic_filebuf, 27_io
 
   - wfilebuf, get variable-encoding working and tested, including
-    positioning and seeking.
+    positioning and seeking. (I think this may be done now)
 
-  - wfilebuf testsuite
+  - wfilebuf testsuite (getting there...)
 
   - look ahead for unbuffered io, so know when multiple putc's can be
     coalesced.
@@ -90,9 +96,13 @@ testsuite
 
 g++/binutils
 
-  - compression for wide versions of basic types
+  - compression for wide versions of basic types, not just narrow
 
-- get Apple's debug mode, or something with equivalent functionality, in.
+threads
+
+  - create MT abstraction layer for atomicity to pthreads.
+
+  - solution for threads + C++.
 
 - audit for places where __builtin_expect can be used.
 
@@ -157,8 +167,6 @@ sources, with macro-guards. Also, same with the TR.
 
 - add feature-test macros for non-standard extensions
 
-- create MT abstraction layer for atomicity to pthreads.
-
 - add MT support for locale, string, istream, ostream
 
 - need to think about doing a .texi or DocBook manual, instead of all
index 6ec7c4b..15e5af4 100644 (file)
@@ -5,8 +5,8 @@
 
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-   <meta name="AUTHOR" content="dgregor@apple.com (Doug Gregor)" />
-   <meta name="KEYWORDS" content="libstdc++, libstdc++-v3, GCC, g++, debug" />
+   <meta name="AUTHOR" content="gregod@cs.rpi.edu (Doug Gregor)" />
+   <meta name="KEYWORDS" content="C++, GCC, libstdc++, g++, debug" />
    <meta name="DESCRIPTION" content="Design of the libstdc++ debug mode." />
    <meta name="GENERATOR" content="vi and eight fingers" />
    <title>Design of the libstdc++ debug mode</title>
   following basic structure:</p>
 
 <pre>
-template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
+template&lt;typename _Tp, typename _Allocator = allocator&lt;_Tp&gt;
   class debug-list :
     public release-list&lt;_Tp, _Allocator&gt;,
     public __gnu_debug::_Safe_sequence&lt;debug-list&lt;_Tp, _Allocator&gt; &gt;
@@ -309,12 +309,14 @@ template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
 
 <p>Achieving link- and run-time coexistence is not a trivial
   implementation task. To achieve this goal we required a small
-  extension to the GNU C++ compiler (described in the section on
-  <a href="#mixing">link- and run-time coexistence</a>) and complex
-  organization of debug- and release-modes. The end result is that we
-  have achieved per-use recompilation but have had to give up some
-  checking of the <code>std::basic_string</code> class template
-  (namely, safe iterators).
+  extension to the GNU C++ compiler (described in the GCC Manual for
+  C++ Extensions, see <a href =
+  http://gcc.gnu.org/onlinedocs/gcc/Strong-Using.html>strong
+  using</a>), and a complex organization of debug- and
+  release-modes. The end result is that we have achieved per-use
+  recompilation but have had to give up some checking of the
+  <code>std::basic_string</code> class template (namely, safe
+  iterators).
 
 <h4><a name="compile_coexistence">Compile-time coexistence of release- and
     debug-mode components</a></h4>
@@ -322,95 +324,129 @@ template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
   components need to exist within a single translation unit so that
   the debug versions can wrap the release versions. However, only one
   of these components should be user-visible at any particular
-  time with the standard name, e.g., <code>std::list</code>. In
-  release mode, we define only the release-mode version of the
+  time with the standard name, e.g., <code>std::list</code>. </p>
+
+<p>In release mode, we define only the release-mode version of the
   component with its standard name and do not include the debugging
-  component at all (except, perhaps, in <code>__gnu_debug</code>, if
-  requested via the separate debugging headers). This method leaves the
-  behavior of release mode completely unchanged from its behavior
-  prior to the introduction of the libstdc++ debug mode.</p>
-
-<p>In debug mode we include the release-mode container into its
-  natural namespace but perform renaming to an implementation-defined
-  name using preprocessor macros. Thus the
-  release-mode <code>std::list</code> will be renamed
-  to <code>std::_Release_list</code> during debug mode, and we will
-  automatically include the debugging version with the
-  name <code>std::list</code> for users to reference. This method
-  allows the debug- and release-mode versions of the same component to
-  coexist at compile-time without causing an unreasonable maintenance
-  burden.</p>
+  component at all. The release mode version is defined within the
+  namespace <code>__gnu_nom</code>, and then associated with namespace
+  <code>std</code> via a "strong using" directive. Minus the
+  namespace associations, this method leaves the behavior of release
+  mode completely unchanged from its behavior prior to the
+  introduction of the libstdc++ debug mode. Here's an example of what
+  this ends up looking like, in C++.</p>
+
+<pre>
+namespace __gnu_norm
+{
+  using namespace std; 
+  
+  template&lt;typename _Tp, typename _Alloc = allocator&lt;_Tp&gt; &gt;
+    class list
+    {
+      // ...
+    };
+} // namespace __gnu_norm
+
+namespace std
+{
+  using namespace __gnu_norm __attribute__ ((strong));
+}
+</pre>
+  
+<p>In debug mode we include the release-mode container and also the
+debug-mode container. The release mode version is defined exactly as
+before, and the debug-mode container is defined within the namespace
+<code>__gnu_debug</code>, which is associated with namespace
+<code>std</code> via a "strong using" directive.  This method allows
+the debug- and release-mode versions of the same component to coexist
+at compile-time without causing an unreasonable maintenance burden,
+while minimizing confusion. Again, this boils down to C++ code as
+follows:</p>
+
+<pre>
+namespace __gnu_norm
+{
+  using namespace std; 
+  
+  template&lt;typename _Tp, typename _Alloc = allocator&lt;_Tp&gt; &gt;
+    class list
+    {
+      // ...
+    };
+} // namespace __gnu_norm
+
+namespace __gnu_debug
+{
+  using namespace std; 
+  
+  template&lt;typename _Tp, typename _Alloc = allocator&lt;_Tp&gt; &gt;
+    class list
+    : public __gnu_norm::list&lt;_Tp, _Alloc&gt;,
+      public __gnu_debug::_Safe_sequence&lt;list&lt;_Tp, _Alloc&gt; &gt;
+    {
+      // ...
+    };
+} // namespace __gnu_norm
+
+namespace std
+{
+  using namespace __gnu_debug __attribute__ ((strong));
+}
+</pre>
 
 <h4><a name="mixing">Link- and run-time coexistence of release- and
     debug-mode components</a></h4>
-<p>There is a problem with the simple compile-time coexistence
-  mechanism: if a user compiles some modules with release mode and
-  some modules with debug mode, the debuggable components will differ
-  in different translation units, violating the C++ One Definition
-  Rule (ODR). This violation will likely be detected at link time,
-  because the sizes of debug-mode containers will differ from the
-  sizes of release-mode containers, although in some cases (such as
-  dynamic linking) the error may be detected much later (or not at
-  all!).</p>
-
-<p>Unfortunately, it is not possible to avoid violating the ODR with
-  most debug mode designs (see the section on <a
-  href="#coexistence_alt">alternatives for coexistence</a>), so the
-  philosophy of the libstdc++ debug mode is to acknowledge that there
-  is an unavoidable ODR violation in this case but to ensure that the
-  ODR violation does not affect execution. To accomplish this, the
-  libstdc++ debug mode uses the aforementioned preprocessor renaming
-  scheme but includes an additional renaming scheme that happens at
-  compile-time that essentially reverses the preprocessor
-  renaming <em>from the linker's point of view</em>. Thus, in debug
-  mode, the release-mode <code>list</code> container is
-  named <code>std::_Release_list</code> but will be mangled with the
-  name <code>std::list</code> (as it was in release mode). Similarly,
-  the debug-mode <code>list</code> is named <code>std::list</code>
-  (in debug mode) but will be mangled
-  as <code>std::_Debug_list</code>. Thus the
-  release-mode <code>list</code> always compiles down to code that
-  uses the name <code>std::list</code>, and the
-  debug-mode <code>list</code> always compiles down to code that uses
-  the name <code>std::_Debug_list</code>, independent of the use of
-  debug mode. This has several positive effects:</p>
 
-<ul>
-  <li>No linking conflicts between debug/release objects: because the
-  names of the debug- and release-mode containers are different in the
-  compiled object files, there are no link-time conflicts between the
-  two.</li>
-
-  <li>Release-mode code is shared: the release-mode code can be shared
-  within a program, even with it is compiled partly in release-mode
-  and partly in debug-mode, because the release-mode code is unchanged
-  in name and function. This can decrease the size of mixed
-  debug/release binaries.</li>
-
-  <li>Able to catch <em>most</em> invalid debug/release combinations:
-  because the names of debug- and release-mode containers are
-  different in the compiled object files, if a debug/release
-  interaction cannot occur (e.g., because a container a translation
-  unit compiled in debug mode is passed to a routine in a translation
-  unit compiled in release mode) the result will be an undefined
-  symbol at link time. The undefined symbol occurs because the mangled
-  name of the definition will contain the release-mode container type
-  and the mangled name of the reference will contain the debug-mode
-  container type. However, we cannot detect these collisions if the
-  only use of the container is in the return type, because the return
-  type is not part of the mangled name of a function.</li>
-</ul>
+<p>Because each component has a distinct and separate release and
+debug implementation, there are are no issues with link-time
+coexistence: the separate namespaces result in different mangled
+names, and thus unique linkage.</p>
+
+<p>However, components that are defined and used within the C++
+standard library itself face additional constraints. For instance,
+some of the member functions of <code> std::moneypunct</code> return
+<code>std::basic_string</code>. Normally, this is not a problem, but
+with a mixed mode standard library that could be using either
+debug-mode or release-mode <code> basic_string</code> objects, things
+get more complicated.  As the return value of a function is not
+encoded into the mangled name, there is no way to specify a
+release-mode or a debug-mode string. In practice, this results in
+runtime errors. A simplified example of this problem is as follows.
+</p>
+
+<p> Take this translation unit, compiled in debug-mode: <p>
+<pre>
+// -D_GLIBCXX_DEBUG
+#include <string>
+
+std::string test02();
+std::string test01()
+{
+  return test02();
+}
+int main()
+{
+  test01();
+  return 0;
+}
+</pre>
 
-<p>The new <code>link_name</code> class attribute facilities
-  renaming. It may be attached to any class type (or any class
-  template) to override the name of the class used for name
-  mangling. For instance, a class named <code>bar</code> would
-  generally mangle as <code>3bar</code>; if the class has
-  a <code>link_name</code> attribute that specifies the string
-  "wibble", then it would mangle as <code>6wibble</code>.</p>
+<p> ... and linked to this translation unit, compiled in release mode:</p>
 
-<p>Note that although we have hidden the ODR violation, it still
-  exists. For this reason we cannot easily provide safe iterators for
+<pre>
+#include <string>
+std::string
+test02()
+{
+  return std::string("toast");
+}
+</pre>
+
+<p> For this reason we cannot easily provide safe iterators for
   the <code>std::basic_string</code> class template, as it is present
   throughout the C++ standard library. For instance, locale facets
   define typedefs that include <code>basic_string</code>: in a mixed
@@ -445,7 +481,7 @@ template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
   release-compiled translation units is enormous.</p>
 
 <h4><a name="coexistence_alt">Alternatives for Coexistence</a></h4>
-<p>The coexistence scheme was chosen over many alternatives,
+<p>The coexistence scheme above was chosen over many alternatives,
   including language-only solutions and solutions that also required
   extensions to the C++ front end. The following is a partial list of
   solutions, with justifications for our rejection of each.</p>
@@ -491,19 +527,12 @@ template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
       declarations disallow specialization. This method fails
       the <b>correctness</b> criteria.</li>
 
-  <li><em>Extension: allow template aliasing/renaming</em>: This is
-    the runner-up to the <code>link_name</code> solution, eliminated
-    only because it requires more extensive compiler changes
-    than <code>link_name</code>. In this model, we would define the
-    debug containers in a different namespace
-    (e.g., <code>__gnu_debug</code>) and then import them (e.g., with
-    an extended <code>using</code> declaration that aliases templates,
-    such as that of <a
-    href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1449.pdf">template
-    aliases</a> proposal). This solution is workable, and in fact
-    would be desirable in the long run, but requires a sizeable change
-    to the C++ compiler front-end that is not within the scope of
-    this project.</li>
+  <li><em> Use implementation-specific properties of anonymous
+    namespaces. </em>
+    See <a
+    href="http://gcc.gnu.org/ml/libstdc++/2003-08/msg00004.html"> this post
+    </a> </li>
+    This method fails the <b>correctness</b> criteria.</li>
 
   <li><em>Extension: allow reopening on namespaces</em>: This would
     allow the debug mode to effectively alias the
@@ -518,6 +547,21 @@ template&lt;typename _Tp, typename _Allocator = std::allocator&lt;_Tp&gt;
     recompilation</b> requirement, because we would only be able to
     support option (1) or (2).</li>
   </li>
+
+  <li><em>Extension: use link name</em>: This option involves
+    complicated re-naming between debug-mode and release-mode
+    components at compile time, and then a g++ extension called <em>
+    link name </em> to recover the original names at link time. There
+    are two drawbacks to this approach. One, it's very verbose,
+    relying on macro renaming at compile time and several levels of
+    include ordering. Two, ODR issues remained with container member
+    functions taking no arguments in mixed-mode settings resulting in
+    equivalent link names, <code> vector::push_back() </code> being
+    one example. 
+    See <a
+    href="http://gcc.gnu.org/ml/libstdc++/2003-08/msg00177.html">link
+    name</a> </li>
+  </li>
 </ul>
 
 <p>Other options may exist for implementing the debug mode, many of