diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d6534c9427f..84f842f2c4a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2001-12-04 Benjamin Kosnik + + * src/Makefile.am (sources): Add ext-inst.cc. + * src/Makefile.in: Regenerate. + * src/ext-inst.cc: New file. + * include/bits/stl_threads.h: Format. + * src/globals.cc: Add instantiation for _S_swap_lock. + + * testsuite/18_support/numeric_limits.cc: Add numeric_limits + instantiation. + +2001-12-04 John David Anglin + + * testsuite/22_locale/numpunct_members_wchar_t.cc: Only compile + and execute test01 if _GLIBCPP_USE_WCHAR_T is defined. + * testsuite/26_numerics/complex_inserters_extractors.cc: Provide + for explicit instantiation of class std::basic_string >. + 2001-12-03 Benjamin Kosnik * testsuite/22_locale/collate.cc: Compile-only. diff --git a/libstdc++-v3/include/bits/stl_threads.h b/libstdc++-v3/include/bits/stl_threads.h index 21b6a1fd43c..0150cd58c85 100644 --- a/libstdc++-v3/include/bits/stl_threads.h +++ b/libstdc++-v3/include/bits/stl_threads.h @@ -53,22 +53,22 @@ namespace std { + // Class _Refcount_Base provides a type, _RC_t, a data member, + // _M_ref_count, and member functions _M_incr and _M_decr, which perform + // atomic preincrement/predecrement. The constructor initializes + // _M_ref_count. + struct _Refcount_Base + { + // The type _RC_t + typedef size_t _RC_t; + + // The data member _M_ref_count + volatile _RC_t _M_ref_count; + + // Constructor + __gthread_mutex_t _M_ref_count_lock; -// Class _Refcount_Base provides a type, _RC_t, a data member, -// _M_ref_count, and member functions _M_incr and _M_decr, which perform -// atomic preincrement/predecrement. The constructor initializes -// _M_ref_count. -struct _Refcount_Base -{ - // The type _RC_t - typedef size_t _RC_t; - - // The data member _M_ref_count - volatile _RC_t _M_ref_count; - - // Constructor - __gthread_mutex_t _M_ref_count_lock; - _Refcount_Base(_RC_t __n) : _M_ref_count(__n) + _Refcount_Base(_RC_t __n) : _M_ref_count(__n) { #ifdef __GTHREAD_MUTEX_INIT __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT; @@ -80,112 +80,128 @@ struct _Refcount_Base #endif } - void _M_incr() { - __gthread_mutex_lock(&_M_ref_count_lock); - ++_M_ref_count; - __gthread_mutex_unlock(&_M_ref_count_lock); - } - _RC_t _M_decr() { - __gthread_mutex_lock(&_M_ref_count_lock); - volatile _RC_t __tmp = --_M_ref_count; - __gthread_mutex_unlock(&_M_ref_count_lock); - return __tmp; - } -}; + void + _M_incr() + { + __gthread_mutex_lock(&_M_ref_count_lock); + ++_M_ref_count; + __gthread_mutex_unlock(&_M_ref_count_lock); + } -// Atomic swap on unsigned long -// This is guaranteed to behave as though it were atomic only if all -// possibly concurrent updates use _Atomic_swap. -// In some cases the operation is emulated with a lock. + _RC_t + _M_decr() + { + __gthread_mutex_lock(&_M_ref_count_lock); + volatile _RC_t __tmp = --_M_ref_count; + __gthread_mutex_unlock(&_M_ref_count_lock); + return __tmp; + } + }; + + // Atomic swap on unsigned long + // This is guaranteed to behave as though it were atomic only if all + // possibly concurrent updates use _Atomic_swap. + // In some cases the operation is emulated with a lock. #if defined (__GTHREAD_MUTEX_INIT) -// This could be optimized to use the atomicity.h abstraction layer. -// vyzo: simple _Atomic_swap implementation following the guidelines above - // We use a template here only to get a unique initialized instance. - template - struct _Swap_lock_struct { - static __gthread_mutex_t _S_swap_lock; - }; + // This could be optimized to use the atomicity.h abstraction layer. + // vyzo: simple _Atomic_swap implementation following the guidelines above + // We use a template here only to get a unique initialized instance. + template + struct _Swap_lock_struct + { static __gthread_mutex_t _S_swap_lock; }; - template + template __gthread_mutex_t _Swap_lock_struct<__dummy>::_S_swap_lock = __GTHREAD_MUTEX_INIT; - // This should be portable, but performance is expected - // to be quite awful. This really needs platform specific - // code. - inline unsigned long _Atomic_swap(unsigned long * __p, unsigned long __q) { - __gthread_mutex_lock(&_Swap_lock_struct<0>::_S_swap_lock); - unsigned long __result = *__p; - *__p = __q; - __gthread_mutex_unlock(&_Swap_lock_struct<0>::_S_swap_lock); - return __result; - } + // This should be portable, but performance is expected to be quite + // awful. This really needs platform specific code. + inline unsigned long + _Atomic_swap(unsigned long * __p, unsigned long __q) + { + __gthread_mutex_lock(&_Swap_lock_struct<0>::_S_swap_lock); + unsigned long __result = *__p; + *__p = __q; + __gthread_mutex_unlock(&_Swap_lock_struct<0>::_S_swap_lock); + return __result; + } #endif -// Locking class. Note that this class *does not have a constructor*. -// It must be initialized either statically, with __STL_MUTEX_INITIALIZER, -// or dynamically, by explicitly calling the _M_initialize member function. -// (This is similar to the ways that a pthreads mutex can be initialized.) -// There are explicit member functions for acquiring and releasing the lock. + // Locking class. Note that this class *does not have a + // constructor*. It must be initialized either statically, with + // __STL_MUTEX_INITIALIZER, or dynamically, by explicitly calling + // the _M_initialize member function. (This is similar to the ways + // that a pthreads mutex can be initialized.) There are explicit + // member functions for acquiring and releasing the lock. -// There is no constructor because static initialization is essential for -// some uses, and only a class aggregate (see section 8.5.1 of the C++ -// standard) can be initialized that way. That means we must have no -// constructors, no base classes, no virtual functions, and no private or -// protected members. + // There is no constructor because static initialization is + // essential for some uses, and only a class aggregate (see section + // 8.5.1 of the C++ standard) can be initialized that way. That + // means we must have no constructors, no base classes, no virtual + // functions, and no private or protected members. #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) -extern __gthread_mutex_t _GLIBCPP_mutex; -extern __gthread_mutex_t *_GLIBCPP_mutex_address; -extern __gthread_once_t _GLIBCPP_once; -extern void _GLIBCPP_mutex_init (void); -extern void _GLIBCPP_mutex_address_init (void); + extern __gthread_mutex_t _GLIBCPP_mutex; + extern __gthread_mutex_t *_GLIBCPP_mutex_address; + extern __gthread_once_t _GLIBCPP_once; + extern void _GLIBCPP_mutex_init (void); + extern void _GLIBCPP_mutex_address_init (void); #endif -struct _STL_mutex_lock -{ - // The class must be statically initialized with __STL_MUTEX_INITIALIZER. + struct _STL_mutex_lock + { + // The class must be statically initialized with __STL_MUTEX_INITIALIZER. #if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - volatile int _M_init_flag; - __gthread_once_t _M_once; + volatile int _M_init_flag; + __gthread_once_t _M_once; #endif - __gthread_mutex_t _M_lock; - void _M_initialize() { + __gthread_mutex_t _M_lock; + + void + _M_initialize() + { #ifdef __GTHREAD_MUTEX_INIT - // There should be no code in this path given the usage rules above. + // There should be no code in this path given the usage rules above. #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (_M_init_flag) return; - if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0 - && __gthread_active_p ()) - abort (); - __gthread_mutex_lock (&_GLIBCPP_mutex); - if (!_M_init_flag) { - // Even though we have a global lock, we use __gthread_once to be - // absolutely certain the _M_lock mutex is only initialized once on - // multiprocessor systems. - _GLIBCPP_mutex_address = &_M_lock; - if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0 + if (_M_init_flag) return; + if (__gthread_once (&_GLIBCPP_once, _GLIBCPP_mutex_init) != 0 + && __gthread_active_p ()) + abort (); + __gthread_mutex_lock (&_GLIBCPP_mutex); + if (!_M_init_flag) + { + // Even though we have a global lock, we use __gthread_once to be + // absolutely certain the _M_lock mutex is only initialized once on + // multiprocessor systems. + _GLIBCPP_mutex_address = &_M_lock; + if (__gthread_once (&_M_once, _GLIBCPP_mutex_address_init) != 0 && __gthread_active_p ()) - abort (); - _M_init_flag = 1; + abort (); + _M_init_flag = 1; + } + __gthread_mutex_unlock (&_GLIBCPP_mutex); +#endif } - __gthread_mutex_unlock (&_GLIBCPP_mutex); -#endif - } - void _M_acquire_lock() { -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (!_M_init_flag) _M_initialize(); -#endif - __gthread_mutex_lock(&_M_lock); - } - void _M_release_lock() { -#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) - if (!_M_init_flag) _M_initialize(); -#endif - __gthread_mutex_unlock(&_M_lock); - } -}; + void + _M_acquire_lock() + { +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + if (!_M_init_flag) _M_initialize(); +#endif + __gthread_mutex_lock(&_M_lock); + } + + void + _M_release_lock() + { +#if !defined(__GTHREAD_MUTEX_INIT) && defined(__GTHREAD_MUTEX_INIT_FUNCTION) + if (!_M_init_flag) _M_initialize(); +#endif + __gthread_mutex_unlock(&_M_lock); + } + }; + #ifdef __GTHREAD_MUTEX_INIT #define __STL_MUTEX_INITIALIZER = { __GTHREAD_MUTEX_INIT } #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) @@ -197,28 +213,24 @@ struct _STL_mutex_lock #endif #endif -// A locking class that uses _STL_mutex_lock. The constructor takes a -// reference to an _STL_mutex_lock, and acquires a lock. The -// destructor releases the lock. It's not clear that this is exactly -// the right functionality. It will probably change in the future. - -struct _STL_auto_lock -{ - _STL_mutex_lock& _M_lock; - - _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) + // A locking class that uses _STL_mutex_lock. The constructor takes a + // reference to an _STL_mutex_lock, and acquires a lock. The + // destructor releases the lock. It's not clear that this is exactly + // the right functionality. It will probably change in the future. + struct _STL_auto_lock + { + _STL_mutex_lock& _M_lock; + + _STL_auto_lock(_STL_mutex_lock& __lock) : _M_lock(__lock) { _M_lock._M_acquire_lock(); } - ~_STL_auto_lock() { _M_lock._M_release_lock(); } -private: - void operator=(const _STL_auto_lock&); - _STL_auto_lock(const _STL_auto_lock&); -}; + ~_STL_auto_lock() { _M_lock._M_release_lock(); } + private: + void operator=(const _STL_auto_lock&); + _STL_auto_lock(const _STL_auto_lock&); + }; + } // namespace std -#endif /* __SGI_STL_INTERNAL_THREADS_H */ - -// Local Variables: -// mode:C++ -// End: +#endif diff --git a/libstdc++-v3/src/Makefile.am b/libstdc++-v3/src/Makefile.am index b32359deae4..0e124046000 100644 --- a/libstdc++-v3/src/Makefile.am +++ b/libstdc++-v3/src/Makefile.am @@ -64,8 +64,9 @@ sources = \ complex_io.cc functexcept.cc globals.cc ios.cc limits.cc \ locale.cc locale-inst.cc localename.cc \ collate.cc messages.cc moneypunct.cc numpunct.cc time.cc \ + vterminate.cc \ misc-inst.cc stdexcept.cc stl-inst.cc string-inst.cc strstream.cc \ - valarray-inst.cc wstring-inst.cc concept-inst.cc vterminate.cc + valarray-inst.cc wstring-inst.cc concept-inst.cc ext-inst.cc VPATH = $(top_srcdir)/src:$(top_srcdir) diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index e57cf7356e3..643aebe7400 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -189,8 +189,9 @@ sources = \ complex_io.cc functexcept.cc globals.cc ios.cc limits.cc \ locale.cc locale-inst.cc localename.cc \ collate.cc messages.cc moneypunct.cc numpunct.cc time.cc \ + vterminate.cc \ misc-inst.cc stdexcept.cc stl-inst.cc string-inst.cc strstream.cc \ - valarray-inst.cc wstring-inst.cc concept-inst.cc vterminate.cc + valarray-inst.cc wstring-inst.cc concept-inst.cc ext-inst.cc VPATH = $(top_srcdir)/src:$(top_srcdir) @@ -266,9 +267,9 @@ LIBS = @LIBS@ libstdc___la_OBJECTS = basic_file.lo bitset.lo c++locale.lo cmath.lo \ codecvt.lo complex_io.lo functexcept.lo globals.lo ios.lo limits.lo \ locale.lo locale-inst.lo localename.lo collate.lo messages.lo \ -moneypunct.lo numpunct.lo time.lo misc-inst.lo stdexcept.lo stl-inst.lo \ -string-inst.lo strstream.lo valarray-inst.lo wstring-inst.lo \ -concept-inst.lo vterminate.lo +moneypunct.lo numpunct.lo time.lo vterminate.lo misc-inst.lo \ +stdexcept.lo stl-inst.lo string-inst.lo strstream.lo valarray-inst.lo \ +wstring-inst.lo concept-inst.lo ext-inst.lo CXXFLAGS = @CXXFLAGS@ CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) CXXLD = $(CXX) diff --git a/libstdc++-v3/src/ext-inst.cc b/libstdc++-v3/src/ext-inst.cc new file mode 100644 index 00000000000..34cd4e6a9fd --- /dev/null +++ b/libstdc++-v3/src/ext-inst.cc @@ -0,0 +1,39 @@ +// Explicit instantiation file. + +// Copyright (C) 2001 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// As a special exception, you may use this file as part of a free software +// library without restriction. Specifically, if other files instantiate +// templates or use macros or inline functions from this file, or you compile +// this file and link it with other files to produce an executable, this +// file does not by itself cause the resulting executable to be covered by +// the GNU General Public License. This exception does not however +// invalidate any other reasons why the executable file might be covered by +// the GNU General Public License. + +// +// ISO C++ 14882: +// + +#include + +namespace std +{ + template const unsigned long rope >::_S_min_len; +} // namespace std diff --git a/libstdc++-v3/src/globals.cc b/libstdc++-v3/src/globals.cc index d7a733e5daa..20fe96994fb 100644 --- a/libstdc++-v3/src/globals.cc +++ b/libstdc++-v3/src/globals.cc @@ -93,8 +93,9 @@ namespace std // function call to initialize a mutex. For example, see stl_threads.h. #if __GTHREADS #ifdef __GTHREAD_MUTEX_INIT - // This path is not needed since static initialization of mutexs works - // on this platform. + // Need to provide explicit instantiations of static data for + // systems with broken weak linkage support. + template __gthread_mutex_t _Swap_lock_struct<0>::_S_swap_lock; #elif defined(__GTHREAD_MUTEX_INIT_FUNCTION) __gthread_once_t _GLIBCPP_once = __GTHREAD_ONCE_INIT; __gthread_mutex_t _GLIBCPP_mutex; diff --git a/libstdc++-v3/src/string-inst.cc b/libstdc++-v3/src/string-inst.cc index 21ae5984527..54249b5d0e6 100644 --- a/libstdc++-v3/src/string-inst.cc +++ b/libstdc++-v3/src/string-inst.cc @@ -21,8 +21,7 @@ // As a special exception, you may use this file as part of a free software // library without restriction. Specifically, if other files instantiate // templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by +// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by // the GNU General Public License. This exception does not however // invalidate any other reasons why the executable file might be covered by // the GNU General Public License. diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits.cc b/libstdc++-v3/testsuite/18_support/numeric_limits.cc index 000577917d1..99450c6acd8 100644 --- a/libstdc++-v3/testsuite/18_support/numeric_limits.cc +++ b/libstdc++-v3/testsuite/18_support/numeric_limits.cc @@ -92,7 +92,10 @@ template operator==(int i) { return i == key; } }; -struct B { }; +struct B +{ + B(int i = 0) { } +}; bool test01() @@ -139,6 +142,8 @@ bool test01() } // test linkage of the generic bits +template struct std::numeric_limits; + void test02() { typedef std::numeric_limits b_nl_type; @@ -176,3 +181,9 @@ int main() return 0; } + + + + + + diff --git a/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc index afb7eb9fbd0..25694f4757a 100644 --- a/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc +++ b/libstdc++-v3/testsuite/22_locale/numpunct_members_wchar_t.cc @@ -26,6 +26,7 @@ // XXX This test is not working for non-glibc locale models. // { dg-do run { xfail *-*-* } } +#ifdef _GLIBCPP_USE_WCHAR_T void test01() { using namespace std; @@ -79,10 +80,12 @@ void test01() VERIFY( dp2 != dp4 ); VERIFY( th2 != th4 ); } +#endif int main() { +#ifdef _GLIBCPP_USE_WCHAR_T test01(); - +#endif return 0; } diff --git a/libstdc++-v3/testsuite/26_numerics/complex_inserters_extractors.cc b/libstdc++-v3/testsuite/26_numerics/complex_inserters_extractors.cc index 8161ee1aeb5..d304aa47b38 100644 --- a/libstdc++-v3/testsuite/26_numerics/complex_inserters_extractors.cc +++ b/libstdc++-v3/testsuite/26_numerics/complex_inserters_extractors.cc @@ -106,6 +106,7 @@ struct gnu_char_traits : public std::char_traits { }; typedef std::basic_ostringstream gnu_sstream; +template class std::basic_string >; void test02() { @@ -143,3 +144,6 @@ main() return 0; } + + +