Update gcc-50 to SVN version 221423
[dragonfly.git] / contrib / gcc-5.0 / libstdc++-v3 / src / c++11 / cxx11-shim_facets.cc
1 // Locale support -*- C++ -*-
2
3 // Copyright (C) 2014-2015 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 //
26 // ISO C++ 14882: 22.1  Locales
27 //
28
29 // This file defines classes that behave like the standard predefined locale
30 // facets (collate, money_get etc.) except that they forward all virtual
31 // functions to another facet which uses a different std::string ABI,
32 // converting between string types as needed.
33 // When a user replaces one of the relevant facets the corresponding shim in
34 // this file is used so that the replacement facet can be used (via the shim)
35 // in code that uses the other std::string ABI from the replacing code.
36
37 #ifndef _GLIBCXX_USE_CXX11_ABI
38 # define _GLIBCXX_USE_CXX11_ABI 1
39 #endif
40 #include <locale>
41
42 #if ! _GLIBCXX_USE_DUAL_ABI
43 # error This file should not be compiled for this configuration.
44 #endif
45
46 namespace std _GLIBCXX_VISIBILITY(default)
47 {
48   // Base class of facet shims, holds a reference to the underlying facet
49   // that the shim forwards to.
50   class locale::facet::__shim
51   {
52   public:
53     const facet* _M_get() const { return _M_facet; }
54
55     __shim(const __shim&) = delete;
56     __shim& operator=(const __shim&) = delete;
57
58   protected:
59     explicit
60     __shim(const facet* __f) : _M_facet(__f) { __f->_M_add_reference(); }
61
62     ~__shim() { _M_facet->_M_remove_reference(); }
63
64   private:
65     const facet* _M_facet;
66   };
67
68 namespace __facet_shims
69 {
70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
71
72   namespace // unnamed
73   {
74     template<typename C>
75       void __destroy_string(void* p)
76       {
77         static_cast<std::basic_string<C>*>(p)->~basic_string();
78       }
79   } // namespace
80
81   // Manages a buffer of uninitialized memory that can store a std::string
82   // or std::wstring, using either ABI, and convert to the other ABI.
83   class __any_string
84   {
85     struct __attribute__((may_alias)) __str_rep
86     {
87       union {
88         const void* _M_p;
89         char* _M_pc;
90 #ifdef _GLIBCXX_USE_WCHAR_T
91         wchar_t* _M_pwc;
92 #endif
93       };
94       size_t _M_len;
95       char _M_unused[16];
96
97       operator const char*() const { return _M_pc; }
98 #ifdef _GLIBCXX_USE_WCHAR_T
99       operator const wchar_t*() const { return _M_pwc; }
100 #endif
101     };
102     union {
103       __str_rep _M_str;
104       char _M_bytes[sizeof(__str_rep)];
105     };
106     using __dtor_func = void(*)(void*);
107     __dtor_func _M_dtor = nullptr;
108
109 #if _GLIBCXX_USE_CXX11_ABI
110     // SSO strings overlay the entire __str_rep structure.
111     static_assert(sizeof(std::string) == sizeof(__str_rep),
112                   "std::string changed size!");
113 #else
114     // COW strings overlay just the pointer, the length is stored manually.
115     static_assert(sizeof(std::string) == sizeof(__str_rep::_M_p),
116                   "std::string changed size!");
117 #endif
118 # ifdef _GLIBCXX_USE_WCHAR_T
119     static_assert(sizeof(std::wstring) == sizeof(std::string),
120                   "std::wstring and std::string are different sizes!");
121 # endif
122
123   public:
124     __any_string() = default;
125     ~__any_string() { if (_M_dtor) _M_dtor(_M_bytes); }
126
127     __any_string(const __any_string&) = delete;
128     __any_string& operator=(const __any_string&) = delete;
129
130     // Store a string (and its length if needed) in the buffer and
131     // set _M_dtor to the function that runs the right destructor.
132     template<typename C>
133       __any_string&
134       operator=(const basic_string<C>& s)
135       {
136         if (_M_dtor)
137           _M_dtor(_M_bytes);
138         ::new(_M_bytes) basic_string<C>(s);
139 #if ! _GLIBCXX_USE_CXX11_ABI
140         _M_str._M_len = s.length();
141 #endif
142         _M_dtor = __destroy_string<C>;
143         return *this;
144       }
145
146     // Create a new string with a copy of the characters in the stored string.
147     // The returned object will match the caller's string ABI, even when the
148     // stored string doesn't.
149     template<typename C>
150       operator basic_string<C>() const
151       {
152         if (!_M_dtor)
153           __throw_logic_error("uninitialized __any_string");
154         return basic_string<C>(static_cast<const C*>(_M_str), _M_str._M_len);
155       }
156   };
157
158   // This file is compiled twice, with and without this macro defined.
159   // Define tag types to distinguish between the two cases and to allow
160   // overloading on the tag.
161   using current_abi = __bool_constant<_GLIBCXX_USE_CXX11_ABI>;
162   using other_abi = __bool_constant<!_GLIBCXX_USE_CXX11_ABI>;
163
164   using facet = locale::facet;
165
166   // Declare the functions that shims defined in this file will call to
167   // perform work in the context of the other ABI.
168   // These will be defined when this file is recompiled for the other ABI
169   // (at which point what is now "current_abi" will become "other_abi").
170
171   template<typename C>
172     void
173     __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*);
174
175   template<typename C>
176     int
177     __collate_compare(other_abi, const facet*, const C*, const C*,
178                       const C*, const C*);
179
180   template<typename C>
181     void
182     __collate_transform(other_abi, const facet*, __any_string&,
183                         const C*, const C*);
184
185   template<typename C>
186     time_base::dateorder
187     __time_get_dateorder(other_abi, const facet* f);
188
189   template<typename C>
190     istreambuf_iterator<C>
191     __time_get(other_abi, const facet* f,
192                istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
193                ios_base& io, ios_base::iostate& err, tm* t, char which);
194
195   template<typename C, bool Intl>
196     void
197     __moneypunct_fill_cache(other_abi, const facet*,
198                             __moneypunct_cache<C, Intl>*);
199
200   template<typename C>
201     istreambuf_iterator<C>
202     __money_get(other_abi, const facet*,
203                 istreambuf_iterator<C>, istreambuf_iterator<C>,
204                 bool, ios_base&, ios_base::iostate&,
205                 long double*, __any_string*);
206
207   template<typename C>
208     ostreambuf_iterator<C>
209     __money_put(other_abi, const facet*, ostreambuf_iterator<C>, bool,
210                 ios_base&, C, long double, const __any_string*);
211
212   template<typename C>
213     messages_base::catalog
214     __messages_open(other_abi, const facet*, const char*, size_t,
215                     const locale&);
216
217   template<typename C>
218     void
219     __messages_get(other_abi, const facet*, __any_string&,
220                    messages_base::catalog, int, int, const C*, size_t);
221
222   template<typename C>
223     void
224     __messages_close(other_abi, const facet*, messages_base::catalog);
225
226   namespace // unnamed
227   {
228     template<typename _CharT>
229       struct numpunct_shim : std::numpunct<_CharT>, facet::__shim
230       {
231         typedef typename numpunct<_CharT>::__cache_type __cache_type;
232
233         // f must point to a type derived from numpunct<C>[abi:other]
234         numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
235         : std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
236         {
237           __numpunct_fill_cache(other_abi{}, f, c);
238         }
239
240         ~numpunct_shim()
241         {
242           // Stop GNU locale's ~numpunct() from freeing the cached string.
243           _M_cache->_M_grouping_size = 0;
244         }
245
246         // No need to override any virtual functions, the base definitions
247         // will return the cached data.
248
249         __cache_type* _M_cache;
250       };
251
252     template<typename _CharT>
253       struct collate_shim : std::collate<_CharT>, facet::__shim
254       {
255         typedef basic_string<_CharT>    string_type;
256
257         // f must point to a type derived from collate<C>[abi:other]
258         collate_shim(const facet* f) : __shim(f) { }
259
260         virtual int
261         do_compare(const _CharT* lo1, const _CharT* hi1,
262                    const _CharT* lo2, const _CharT* hi2) const
263         {
264           return __collate_compare(other_abi{}, _M_get(),
265                                    lo1, hi1, lo2, hi2);
266         }
267
268         virtual string_type
269         do_transform(const _CharT* lo, const _CharT* hi) const
270         {
271           __any_string st;
272           __collate_transform(other_abi{}, _M_get(), st, lo, hi);
273           return st;
274         }
275       };
276
277     template<typename _CharT>
278       struct time_get_shim : std::time_get<_CharT>, facet::__shim
279       {
280         typedef typename std::time_get<_CharT>::iter_type iter_type;
281         typedef typename std::time_get<_CharT>::char_type char_type;
282
283         // f must point to a type derived from time_get<C>[abi:other]
284         time_get_shim(const facet* f) : __shim(f) { }
285
286         virtual time_base::dateorder
287         do_date_order() const
288         { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
289
290         virtual iter_type
291         do_get_time(iter_type beg, iter_type end, ios_base& io,
292                     ios_base::iostate& err, tm* t) const
293         {
294           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
295                             't');
296         }
297
298         virtual iter_type
299         do_get_date(iter_type beg, iter_type end, ios_base& io,
300                     ios_base::iostate& err, tm* t) const
301         {
302           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
303                             'd');
304         }
305
306         virtual iter_type
307         do_get_weekday(iter_type beg, iter_type end, ios_base& io,
308                        ios_base::iostate& err, tm* t) const
309         {
310           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
311                             'w');
312         }
313
314         virtual iter_type
315         do_get_monthname(iter_type beg, iter_type end, ios_base& io,
316                          ios_base::iostate& err, tm* t) const
317         {
318           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
319                             'm');
320         }
321
322         virtual iter_type
323         do_get_year(iter_type beg, iter_type end, ios_base& io,
324                     ios_base::iostate& err, tm* t) const
325         {
326           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
327                             'y');
328         }
329       };
330
331     template<typename _CharT, bool _Intl>
332       struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, facet::__shim
333       {
334         typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
335
336         // f must point to a type derived from moneypunct<C>[abi:other]
337         moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
338         : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
339         {
340           __moneypunct_fill_cache(other_abi{}, f, c);
341         }
342
343         ~moneypunct_shim()
344         {
345           // Stop GNU locale's ~moneypunct() from freeing the cached strings.
346           _M_cache->_M_grouping_size = 0;
347           _M_cache->_M_curr_symbol_size = 0;
348           _M_cache->_M_positive_sign_size = 0;
349           _M_cache->_M_negative_sign_size = 0;
350         }
351
352         // No need to override any virtual functions, the base definitions
353         // will return the cached data.
354
355         __cache_type* _M_cache;
356       };
357
358     template<typename _CharT>
359       struct money_get_shim : std::money_get<_CharT>, facet::__shim
360       {
361         typedef typename std::money_get<_CharT>::iter_type iter_type;
362         typedef typename std::money_get<_CharT>::char_type char_type;
363         typedef typename std::money_get<_CharT>::string_type string_type;
364
365         // f must point to a type derived from money_get<C>[abi:other]
366         money_get_shim(const facet* f) : __shim(f) { }
367
368         virtual iter_type
369         do_get(iter_type s, iter_type end, bool intl, ios_base& io,
370                ios_base::iostate& err, long double& units) const
371         {
372           ios_base::iostate err2 = ios_base::goodbit;
373           long double units2;
374           s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
375                           &units2, nullptr);
376           if (err2 == ios_base::goodbit)
377             units = units2;
378           else
379             err = err2;
380           return s;
381         }
382
383         virtual iter_type
384         do_get(iter_type s, iter_type end, bool intl, ios_base& io,
385                ios_base::iostate& err, string_type& digits) const
386         {
387           __any_string st;
388           ios_base::iostate err2 = ios_base::goodbit;
389           s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
390                           nullptr, &st);
391           if (err2 == ios_base::goodbit)
392             digits = st;
393           else
394             err = err2;
395           return s;
396         }
397       };
398
399     template<typename _CharT>
400       struct money_put_shim : std::money_put<_CharT>, facet::__shim
401       {
402         typedef typename std::money_put<_CharT>::iter_type iter_type;
403         typedef typename std::money_put<_CharT>::char_type char_type;
404         typedef typename std::money_put<_CharT>::string_type string_type;
405
406         // f must point to a type derived from money_put<C>[abi:other]
407         money_put_shim(const facet* f) : __shim(f) { }
408
409         virtual iter_type
410         do_put(iter_type s, bool intl, ios_base& io,
411                char_type fill, long double units) const
412         {
413           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
414                              nullptr);
415         }
416
417         virtual iter_type
418         do_put(iter_type s, bool intl, ios_base& io,
419                char_type fill, const string_type& digits) const
420         {
421           __any_string st;
422           st = digits;
423           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
424                              &st);
425         }
426       };
427
428     template<typename _CharT>
429       struct messages_shim : std::messages<_CharT>, facet::__shim
430       {
431         typedef messages_base::catalog  catalog;
432         typedef basic_string<_CharT>    string_type;
433
434         // f must point to a type derived from messages<C>[abi:other]
435         messages_shim(const facet* f) : __shim(f) { }
436
437         virtual catalog
438         do_open(const basic_string<char>& s, const locale& l) const
439         {
440           return __messages_open<_CharT>(other_abi{}, _M_get(),
441                                          s.c_str(), s.size(), l);
442         }
443
444         virtual string_type
445         do_get(catalog c, int set, int msgid, const string_type& dfault) const
446         {
447           __any_string st;
448           __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
449                          dfault.c_str(), dfault.size());
450           return st;
451         }
452
453         virtual void
454         do_close(catalog c) const
455         {
456           __messages_close<_CharT>(other_abi{}, _M_get(), c);
457         }
458       };
459
460     template class numpunct_shim<char>;
461     template class collate_shim<char>;
462     template class moneypunct_shim<char, true>;
463     template class moneypunct_shim<char, false>;
464     template class money_get_shim<char>;
465     template class money_put_shim<char>;
466     template class messages_shim<char>;
467 #ifdef _GLIBCXX_USE_WCHAR_T
468     template class numpunct_shim<wchar_t>;
469     template class collate_shim<wchar_t>;
470     template class moneypunct_shim<wchar_t, true>;
471     template class moneypunct_shim<wchar_t, false>;
472     template class money_get_shim<wchar_t>;
473     template class money_put_shim<wchar_t>;
474     template class messages_shim<wchar_t>;
475 #endif
476
477     template<typename C>
478       inline size_t
479       __copy(const C*& dest, const basic_string<C>& s)
480       {
481         auto len = s.length();
482         C* p = new C[len+1];
483         s.copy(p, len);
484         p[len] = '\0';
485         dest = p;
486         return len;
487       }
488
489   } // namespace
490
491   // Now define and instantiate the functions that will be called by the
492   // shim facets defined when this file is recompiled for the other ABI.
493
494   // Cache the values returned by the numpunct facet f.
495   // Sets c->_M_allocated so that the __numpunct_cache destructor will
496   // delete[] the strings allocated by this function.
497   template<typename C>
498     void
499     __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
500     {
501       auto* m = static_cast<const numpunct<C>*>(f);
502
503       c->_M_decimal_point = m->decimal_point();
504       c->_M_thousands_sep = m->thousands_sep();
505
506       c->_M_grouping = nullptr;
507       c->_M_truename = nullptr;
508       c->_M_falsename = nullptr;
509       // set _M_allocated so that if any allocation fails the previously
510       // allocated strings will be deleted in ~__numpunct_cache()
511       c->_M_allocated = true;
512
513       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
514       c->_M_truename_size = __copy(c->_M_truename, m->truename());
515       c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
516     }
517
518   template void
519   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
520
521 #ifdef _GLIBCXX_USE_WCHAR_T
522   template void
523   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
524 #endif
525
526   template<typename C>
527     int
528     __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
529                       const C* lo2, const C* hi2)
530     {
531       return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
532     }
533
534   template int
535   __collate_compare(current_abi, const facet*, const char*, const char*,
536                     const char*, const char*);
537
538 #ifdef _GLIBCXX_USE_WCHAR_T
539   template int
540   __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
541                     const wchar_t*, const wchar_t*);
542 #endif
543
544   template<typename C>
545     void
546     __collate_transform(current_abi, const facet* f, __any_string& st,
547                         const C* __lo, const C* __hi)
548     {
549       auto* c = static_cast<const collate<C>*>(f);
550       st = c->transform(__lo, __hi);
551     }
552
553   template void
554   __collate_transform(current_abi, const facet*, __any_string&,
555                       const char*, const char*);
556
557 #ifdef _GLIBCXX_USE_WCHAR_T
558   template void
559   __collate_transform(current_abi, const facet*, __any_string&,
560                       const wchar_t*, const wchar_t*);
561 #endif
562
563   // Cache the values returned by the moneypunct facet, f.
564   // Sets c->_M_allocated so that the __moneypunct_cache destructor will
565   // delete[] the strings allocated by this function.
566   template<typename C, bool Intl>
567     void
568     __moneypunct_fill_cache(current_abi, const facet* f,
569                             __moneypunct_cache<C, Intl>* c)
570     {
571       auto* m = static_cast<const moneypunct<C, Intl>*>(f);
572
573       c->_M_decimal_point = m->decimal_point();
574       c->_M_thousands_sep = m->thousands_sep();
575       c->_M_frac_digits = m->frac_digits();
576
577       c->_M_grouping = nullptr;
578       c->_M_curr_symbol = nullptr;
579       c->_M_positive_sign = nullptr;
580       c->_M_negative_sign = nullptr;
581       // Set _M_allocated so that if any allocation fails the previously
582       // allocated strings will be deleted in ~__moneypunct_cache().
583       c->_M_allocated = true;
584
585       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
586       c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
587       c->_M_positive_sign_size
588         = __copy(c->_M_positive_sign, m->positive_sign());
589       c->_M_negative_sign_size
590         = __copy(c->_M_negative_sign, m->negative_sign());
591
592       c->_M_pos_format = m->pos_format();
593       c->_M_neg_format = m->neg_format();
594     }
595
596   template void
597   __moneypunct_fill_cache(current_abi, const facet*,
598                           __moneypunct_cache<char, true>*);
599
600   template void
601   __moneypunct_fill_cache(current_abi, const facet*,
602                           __moneypunct_cache<char, false>*);
603
604 #ifdef _GLIBCXX_USE_WCHAR_T
605   template void
606   __moneypunct_fill_cache(current_abi, const facet*,
607                           __moneypunct_cache<wchar_t, true>*);
608
609   template void
610   __moneypunct_fill_cache(current_abi, const facet*,
611                           __moneypunct_cache<wchar_t, false>*);
612 #endif
613
614   template<typename C>
615     messages_base::catalog
616     __messages_open(current_abi, const facet* f, const char* s, size_t n,
617                     const locale& l)
618     {
619       auto* m = static_cast<const messages<C>*>(f);
620       string str(s, n);
621       return m->open(str, l);
622     }
623
624   template messages_base::catalog
625   __messages_open<char>(current_abi, const facet*, const char*, size_t,
626                         const locale&);
627
628 #ifdef _GLIBCXX_USE_WCHAR_T
629   template messages_base::catalog
630   __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
631                            const locale&);
632 #endif
633
634   template<typename C>
635     void
636     __messages_get(current_abi, const facet* f, __any_string& st,
637                    messages_base::catalog c, int set, int msgid,
638                    const C* s, size_t n)
639     {
640       auto* m = static_cast<const messages<C>*>(f);
641       st = m->get(c, set, msgid, basic_string<C>(s, n));
642     }
643
644   template void
645   __messages_get(current_abi, const facet*, __any_string&,
646                  messages_base::catalog, int, int, const char*, size_t);
647
648 #ifdef _GLIBCXX_USE_WCHAR_T
649   template void
650   __messages_get(current_abi, const facet*, __any_string&,
651                  messages_base::catalog, int, int, const wchar_t*, size_t);
652 #endif
653
654   template<typename C>
655     void
656     __messages_close(current_abi, const facet* f, messages_base::catalog c)
657     {
658       static_cast<const messages<C>*>(f)->close(c);
659     }
660
661   template void
662   __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
663
664 #ifdef _GLIBCXX_USE_WCHAR_T
665   template void
666   __messages_close<wchar_t>(current_abi, const facet*,
667                             messages_base::catalog c);
668 #endif
669
670   template<typename C>
671     time_base::dateorder
672     __time_get_dateorder(current_abi, const facet* f)
673     { return static_cast<const time_get<C>*>(f)->date_order(); }
674
675   template time_base::dateorder
676   __time_get_dateorder<char>(current_abi, const facet*);
677
678 #ifdef _GLIBCXX_USE_WCHAR_T
679   template time_base::dateorder
680   __time_get_dateorder<wchar_t>(current_abi, const facet*);
681 #endif
682
683   template<typename C>
684     istreambuf_iterator<C>
685     __time_get(current_abi, const facet* f,
686                istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
687                ios_base& io, ios_base::iostate& err, tm* t, char which)
688     {
689       auto* g = static_cast<const time_get<C>*>(f);
690       switch(which)
691       {
692       case 't':
693         return g->get_time(beg, end, io, err, t);
694       case 'd':
695         return g->get_date(beg, end, io, err, t);
696       case 'w':
697         return g->get_weekday(beg, end, io, err, t);
698       case 'm':
699         return g->get_monthname(beg, end, io, err, t);
700       case 'y':
701         return g->get_year(beg, end, io, err, t);
702       default:
703         __builtin_unreachable();
704       }
705     }
706
707   template istreambuf_iterator<char>
708   __time_get(current_abi, const facet*,
709              istreambuf_iterator<char>, istreambuf_iterator<char>,
710              ios_base&, ios_base::iostate&, tm*, char);
711
712 #ifdef _GLIBCXX_USE_WCHAR_T
713   template istreambuf_iterator<wchar_t>
714   __time_get(current_abi, const facet*,
715              istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
716              ios_base&, ios_base::iostate&, tm*, char);
717 #endif
718
719   template<typename C>
720     istreambuf_iterator<C>
721     __money_get(current_abi, const facet* f,
722                 istreambuf_iterator<C> s, istreambuf_iterator<C> end,
723                 bool intl, ios_base& str, ios_base::iostate& err,
724                 long double* units, __any_string* digits)
725     {
726       auto* m = static_cast<const money_get<C>*>(f);
727       if (units)
728         return m->get(s, end, intl, str, err, *units);
729       basic_string<C> digits2;
730       s = m->get(s, end, intl, str, err, digits2);
731       if (err == ios_base::goodbit)
732         *digits = digits2;
733       return s;
734     }
735
736   template istreambuf_iterator<char>
737   __money_get(current_abi, const facet*,
738               istreambuf_iterator<char>, istreambuf_iterator<char>,
739               bool, ios_base&, ios_base::iostate&,
740               long double*, __any_string*);
741
742 #ifdef _GLIBCXX_USE_WCHAR_T
743   template istreambuf_iterator<wchar_t>
744   __money_get(current_abi, const facet*,
745               istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
746               bool, ios_base&, ios_base::iostate&,
747               long double*, __any_string*);
748 #endif
749
750   template<typename C>
751     ostreambuf_iterator<C>
752     __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
753                 bool intl, ios_base& io, C fill, long double units,
754                 const __any_string* digits)
755     {
756       auto* m = static_cast<const money_put<C>*>(f);
757       if (digits)
758         return m->put(s, intl, io, fill, *digits);
759       else
760         return m->put(s, intl, io, fill, units);
761     }
762
763   template ostreambuf_iterator<char>
764   __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
765                 bool, ios_base&, char, long double, const __any_string*);
766
767 #ifdef _GLIBCXX_USE_WCHAR_T
768   template ostreambuf_iterator<wchar_t>
769   __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
770                 bool, ios_base&, wchar_t, long double, const __any_string*);
771 #endif
772
773 _GLIBCXX_END_NAMESPACE_VERSION
774 } // namespace __facet_shims
775
776 _GLIBCXX_BEGIN_NAMESPACE_VERSION
777   // Create a new shim facet of type WHICH that forwards calls to F.
778   // F is the replacement facet provided by the user, WHICH is the ID of
779   // F's "other ABI twin" which we are replacing with a shim.
780   const locale::facet*
781 #if _GLIBCXX_USE_CXX11_ABI
782   locale::facet::_M_sso_shim(const locale::id* which) const
783 #else
784   locale::facet::_M_cow_shim(const locale::id* which) const
785 #endif
786   {
787     using namespace __facet_shims;
788
789 #if __cpp_rtti
790     // If this is already a shim just use its underlying facet.
791     if (auto* p = dynamic_cast<const __shim*>(this))
792       return p->_M_get();
793 #endif
794
795     if (which == &numpunct<char>::id)
796       return new numpunct_shim<char>{this};
797     if (which == &std::collate<char>::id)
798       return new collate_shim<char>{this};
799     if (which == &time_get<char>::id)
800       return new time_get_shim<char>{this};
801     if (which == &money_get<char>::id)
802       return new money_get_shim<char>{this};
803     if (which == &money_put<char>::id)
804       return new money_put_shim<char>{this};
805     if (which == &moneypunct<char, true>::id)
806       return new moneypunct_shim<char, true>{this};
807     if (which == &moneypunct<char, false>::id)
808       return new moneypunct_shim<char, false>{this};
809     if (which == &std::messages<char>::id)
810       return new messages_shim<char>{this};
811 #ifdef _GLIBCXX_USE_WCHAR_T
812     if (which == &numpunct<wchar_t>::id)
813       return new numpunct_shim<wchar_t>{this};
814     if (which == &std::collate<wchar_t>::id)
815       return new collate_shim<wchar_t>{this};
816     if (which == &time_get<wchar_t>::id)
817       return new time_get_shim<wchar_t>{this};
818     if (which == &money_get<wchar_t>::id)
819       return new money_get_shim<wchar_t>{this};
820     if (which == &money_put<wchar_t>::id)
821       return new money_put_shim<wchar_t>{this};
822     if (which == &moneypunct<wchar_t, true>::id)
823       return new moneypunct_shim<wchar_t, true>{this};
824     if (which == &moneypunct<wchar_t, false>::id)
825       return new moneypunct_shim<wchar_t, false>{this};
826     if (which == &std::messages<wchar_t>::id)
827       return new messages_shim<wchar_t>{this};
828 #endif
829     __throw_logic_error("cannot create shim for unknown locale::facet");
830   }
831
832 _GLIBCXX_END_NAMESPACE_VERSION
833 } // namespace std