Update gcc-50 to SVN version 221572
[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       _GLIBCXX_DEFAULT_ABI_TAG
151       operator basic_string<C>() const
152       {
153         if (!_M_dtor)
154           __throw_logic_error("uninitialized __any_string");
155         return basic_string<C>(static_cast<const C*>(_M_str), _M_str._M_len);
156       }
157   };
158
159   // This file is compiled twice, with and without this macro defined.
160   // Define tag types to distinguish between the two cases and to allow
161   // overloading on the tag.
162   using current_abi = __bool_constant<_GLIBCXX_USE_CXX11_ABI>;
163   using other_abi = __bool_constant<!_GLIBCXX_USE_CXX11_ABI>;
164
165   using facet = locale::facet;
166
167   // Declare the functions that shims defined in this file will call to
168   // perform work in the context of the other ABI.
169   // These will be defined when this file is recompiled for the other ABI
170   // (at which point what is now "current_abi" will become "other_abi").
171
172   template<typename C>
173     void
174     __numpunct_fill_cache(other_abi, const facet*, __numpunct_cache<C>*);
175
176   template<typename C>
177     int
178     __collate_compare(other_abi, const facet*, const C*, const C*,
179                       const C*, const C*);
180
181   template<typename C>
182     void
183     __collate_transform(other_abi, const facet*, __any_string&,
184                         const C*, const C*);
185
186   template<typename C>
187     time_base::dateorder
188     __time_get_dateorder(other_abi, const facet* f);
189
190   template<typename C>
191     istreambuf_iterator<C>
192     __time_get(other_abi, const facet* f,
193                istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
194                ios_base& io, ios_base::iostate& err, tm* t, char which);
195
196   template<typename C, bool Intl>
197     void
198     __moneypunct_fill_cache(other_abi, const facet*,
199                             __moneypunct_cache<C, Intl>*);
200
201   template<typename C>
202     istreambuf_iterator<C>
203     __money_get(other_abi, const facet*,
204                 istreambuf_iterator<C>, istreambuf_iterator<C>,
205                 bool, ios_base&, ios_base::iostate&,
206                 long double*, __any_string*);
207
208   template<typename C>
209     ostreambuf_iterator<C>
210     __money_put(other_abi, const facet*, ostreambuf_iterator<C>, bool,
211                 ios_base&, C, long double, const __any_string*);
212
213   template<typename C>
214     messages_base::catalog
215     __messages_open(other_abi, const facet*, const char*, size_t,
216                     const locale&);
217
218   template<typename C>
219     void
220     __messages_get(other_abi, const facet*, __any_string&,
221                    messages_base::catalog, int, int, const C*, size_t);
222
223   template<typename C>
224     void
225     __messages_close(other_abi, const facet*, messages_base::catalog);
226
227   namespace // unnamed
228   {
229     template<typename _CharT>
230       struct numpunct_shim : std::numpunct<_CharT>, facet::__shim
231       {
232         typedef typename numpunct<_CharT>::__cache_type __cache_type;
233
234         // f must point to a type derived from numpunct<C>[abi:other]
235         numpunct_shim(const facet* f, __cache_type* c = new __cache_type)
236         : std::numpunct<_CharT>(c), __shim(f), _M_cache(c)
237         {
238           __numpunct_fill_cache(other_abi{}, f, c);
239         }
240
241         ~numpunct_shim()
242         {
243           // Stop GNU locale's ~numpunct() from freeing the cached string.
244           _M_cache->_M_grouping_size = 0;
245         }
246
247         // No need to override any virtual functions, the base definitions
248         // will return the cached data.
249
250         __cache_type* _M_cache;
251       };
252
253     template<typename _CharT>
254       struct collate_shim : std::collate<_CharT>, facet::__shim
255       {
256         typedef basic_string<_CharT>    string_type;
257
258         // f must point to a type derived from collate<C>[abi:other]
259         collate_shim(const facet* f) : __shim(f) { }
260
261         virtual int
262         do_compare(const _CharT* lo1, const _CharT* hi1,
263                    const _CharT* lo2, const _CharT* hi2) const
264         {
265           return __collate_compare(other_abi{}, _M_get(),
266                                    lo1, hi1, lo2, hi2);
267         }
268
269         virtual string_type
270         do_transform(const _CharT* lo, const _CharT* hi) const
271         {
272           __any_string st;
273           __collate_transform(other_abi{}, _M_get(), st, lo, hi);
274           return st;
275         }
276       };
277
278     template<typename _CharT>
279       struct time_get_shim : std::time_get<_CharT>, facet::__shim
280       {
281         typedef typename std::time_get<_CharT>::iter_type iter_type;
282         typedef typename std::time_get<_CharT>::char_type char_type;
283
284         // f must point to a type derived from time_get<C>[abi:other]
285         time_get_shim(const facet* f) : __shim(f) { }
286
287         virtual time_base::dateorder
288         do_date_order() const
289         { return __time_get_dateorder<_CharT>(other_abi{}, _M_get()); }
290
291         virtual iter_type
292         do_get_time(iter_type beg, iter_type end, ios_base& io,
293                     ios_base::iostate& err, tm* t) const
294         {
295           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
296                             't');
297         }
298
299         virtual iter_type
300         do_get_date(iter_type beg, iter_type end, ios_base& io,
301                     ios_base::iostate& err, tm* t) const
302         {
303           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
304                             'd');
305         }
306
307         virtual iter_type
308         do_get_weekday(iter_type beg, iter_type end, ios_base& io,
309                        ios_base::iostate& err, tm* t) const
310         {
311           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
312                             'w');
313         }
314
315         virtual iter_type
316         do_get_monthname(iter_type beg, iter_type end, ios_base& io,
317                          ios_base::iostate& err, tm* t) const
318         {
319           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
320                             'm');
321         }
322
323         virtual iter_type
324         do_get_year(iter_type beg, iter_type end, ios_base& io,
325                     ios_base::iostate& err, tm* t) const
326         {
327           return __time_get(other_abi{}, _M_get(), beg, end, io, err, t,
328                             'y');
329         }
330       };
331
332     template<typename _CharT, bool _Intl>
333       struct moneypunct_shim : std::moneypunct<_CharT, _Intl>, facet::__shim
334       {
335         typedef typename moneypunct<_CharT, _Intl>::__cache_type __cache_type;
336
337         // f must point to a type derived from moneypunct<C>[abi:other]
338         moneypunct_shim(const facet* f, __cache_type* c = new __cache_type)
339         : std::moneypunct<_CharT, _Intl>(c), __shim(f), _M_cache(c)
340         {
341           __moneypunct_fill_cache(other_abi{}, f, c);
342         }
343
344         ~moneypunct_shim()
345         {
346           // Stop GNU locale's ~moneypunct() from freeing the cached strings.
347           _M_cache->_M_grouping_size = 0;
348           _M_cache->_M_curr_symbol_size = 0;
349           _M_cache->_M_positive_sign_size = 0;
350           _M_cache->_M_negative_sign_size = 0;
351         }
352
353         // No need to override any virtual functions, the base definitions
354         // will return the cached data.
355
356         __cache_type* _M_cache;
357       };
358
359     template<typename _CharT>
360       struct money_get_shim : std::money_get<_CharT>, facet::__shim
361       {
362         typedef typename std::money_get<_CharT>::iter_type iter_type;
363         typedef typename std::money_get<_CharT>::char_type char_type;
364         typedef typename std::money_get<_CharT>::string_type string_type;
365
366         // f must point to a type derived from money_get<C>[abi:other]
367         money_get_shim(const facet* f) : __shim(f) { }
368
369         virtual iter_type
370         do_get(iter_type s, iter_type end, bool intl, ios_base& io,
371                ios_base::iostate& err, long double& units) const
372         {
373           ios_base::iostate err2 = ios_base::goodbit;
374           long double units2;
375           s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
376                           &units2, nullptr);
377           if (err2 == ios_base::goodbit)
378             units = units2;
379           else
380             err = err2;
381           return s;
382         }
383
384         virtual iter_type
385         do_get(iter_type s, iter_type end, bool intl, ios_base& io,
386                ios_base::iostate& err, string_type& digits) const
387         {
388           __any_string st;
389           ios_base::iostate err2 = ios_base::goodbit;
390           s = __money_get(other_abi{}, _M_get(), s, end, intl, io, err2,
391                           nullptr, &st);
392           if (err2 == ios_base::goodbit)
393             digits = st;
394           else
395             err = err2;
396           return s;
397         }
398       };
399
400     template<typename _CharT>
401       struct money_put_shim : std::money_put<_CharT>, facet::__shim
402       {
403         typedef typename std::money_put<_CharT>::iter_type iter_type;
404         typedef typename std::money_put<_CharT>::char_type char_type;
405         typedef typename std::money_put<_CharT>::string_type string_type;
406
407         // f must point to a type derived from money_put<C>[abi:other]
408         money_put_shim(const facet* f) : __shim(f) { }
409
410         virtual iter_type
411         do_put(iter_type s, bool intl, ios_base& io,
412                char_type fill, long double units) const
413         {
414           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, units,
415                              nullptr);
416         }
417
418         virtual iter_type
419         do_put(iter_type s, bool intl, ios_base& io,
420                char_type fill, const string_type& digits) const
421         {
422           __any_string st;
423           st = digits;
424           return __money_put(other_abi{}, _M_get(), s, intl, io, fill, 0.L,
425                              &st);
426         }
427       };
428
429     template<typename _CharT>
430       struct messages_shim : std::messages<_CharT>, facet::__shim
431       {
432         typedef messages_base::catalog  catalog;
433         typedef basic_string<_CharT>    string_type;
434
435         // f must point to a type derived from messages<C>[abi:other]
436         messages_shim(const facet* f) : __shim(f) { }
437
438         virtual catalog
439         do_open(const basic_string<char>& s, const locale& l) const
440         {
441           return __messages_open<_CharT>(other_abi{}, _M_get(),
442                                          s.c_str(), s.size(), l);
443         }
444
445         virtual string_type
446         do_get(catalog c, int set, int msgid, const string_type& dfault) const
447         {
448           __any_string st;
449           __messages_get(other_abi{}, _M_get(), st, c, set, msgid,
450                          dfault.c_str(), dfault.size());
451           return st;
452         }
453
454         virtual void
455         do_close(catalog c) const
456         {
457           __messages_close<_CharT>(other_abi{}, _M_get(), c);
458         }
459       };
460
461     template class numpunct_shim<char>;
462     template class collate_shim<char>;
463     template class moneypunct_shim<char, true>;
464     template class moneypunct_shim<char, false>;
465     template class money_get_shim<char>;
466     template class money_put_shim<char>;
467     template class messages_shim<char>;
468 #ifdef _GLIBCXX_USE_WCHAR_T
469     template class numpunct_shim<wchar_t>;
470     template class collate_shim<wchar_t>;
471     template class moneypunct_shim<wchar_t, true>;
472     template class moneypunct_shim<wchar_t, false>;
473     template class money_get_shim<wchar_t>;
474     template class money_put_shim<wchar_t>;
475     template class messages_shim<wchar_t>;
476 #endif
477
478     template<typename C>
479       inline size_t
480       __copy(const C*& dest, const basic_string<C>& s)
481       {
482         auto len = s.length();
483         C* p = new C[len+1];
484         s.copy(p, len);
485         p[len] = '\0';
486         dest = p;
487         return len;
488       }
489
490   } // namespace
491
492   // Now define and instantiate the functions that will be called by the
493   // shim facets defined when this file is recompiled for the other ABI.
494
495   // Cache the values returned by the numpunct facet f.
496   // Sets c->_M_allocated so that the __numpunct_cache destructor will
497   // delete[] the strings allocated by this function.
498   template<typename C>
499     void
500     __numpunct_fill_cache(current_abi, const facet* f, __numpunct_cache<C>* c)
501     {
502       auto* m = static_cast<const numpunct<C>*>(f);
503
504       c->_M_decimal_point = m->decimal_point();
505       c->_M_thousands_sep = m->thousands_sep();
506
507       c->_M_grouping = nullptr;
508       c->_M_truename = nullptr;
509       c->_M_falsename = nullptr;
510       // set _M_allocated so that if any allocation fails the previously
511       // allocated strings will be deleted in ~__numpunct_cache()
512       c->_M_allocated = true;
513
514       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
515       c->_M_truename_size = __copy(c->_M_truename, m->truename());
516       c->_M_falsename_size = __copy(c->_M_falsename, m->falsename());
517     }
518
519   template void
520   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<char>*);
521
522 #ifdef _GLIBCXX_USE_WCHAR_T
523   template void
524   __numpunct_fill_cache(current_abi, const facet*, __numpunct_cache<wchar_t>*);
525 #endif
526
527   template<typename C>
528     int
529     __collate_compare(current_abi, const facet* f, const C* lo1, const C* hi1,
530                       const C* lo2, const C* hi2)
531     {
532       return static_cast<const collate<C>*>(f)->compare(lo1, hi1, lo2, hi2);
533     }
534
535   template int
536   __collate_compare(current_abi, const facet*, const char*, const char*,
537                     const char*, const char*);
538
539 #ifdef _GLIBCXX_USE_WCHAR_T
540   template int
541   __collate_compare(current_abi, const facet*, const wchar_t*, const wchar_t*,
542                     const wchar_t*, const wchar_t*);
543 #endif
544
545   template<typename C>
546     void
547     __collate_transform(current_abi, const facet* f, __any_string& st,
548                         const C* __lo, const C* __hi)
549     {
550       auto* c = static_cast<const collate<C>*>(f);
551       st = c->transform(__lo, __hi);
552     }
553
554   template void
555   __collate_transform(current_abi, const facet*, __any_string&,
556                       const char*, const char*);
557
558 #ifdef _GLIBCXX_USE_WCHAR_T
559   template void
560   __collate_transform(current_abi, const facet*, __any_string&,
561                       const wchar_t*, const wchar_t*);
562 #endif
563
564   // Cache the values returned by the moneypunct facet, f.
565   // Sets c->_M_allocated so that the __moneypunct_cache destructor will
566   // delete[] the strings allocated by this function.
567   template<typename C, bool Intl>
568     void
569     __moneypunct_fill_cache(current_abi, const facet* f,
570                             __moneypunct_cache<C, Intl>* c)
571     {
572       auto* m = static_cast<const moneypunct<C, Intl>*>(f);
573
574       c->_M_decimal_point = m->decimal_point();
575       c->_M_thousands_sep = m->thousands_sep();
576       c->_M_frac_digits = m->frac_digits();
577
578       c->_M_grouping = nullptr;
579       c->_M_curr_symbol = nullptr;
580       c->_M_positive_sign = nullptr;
581       c->_M_negative_sign = nullptr;
582       // Set _M_allocated so that if any allocation fails the previously
583       // allocated strings will be deleted in ~__moneypunct_cache().
584       c->_M_allocated = true;
585
586       c->_M_grouping_size = __copy(c->_M_grouping, m->grouping());
587       c->_M_curr_symbol_size = __copy(c->_M_curr_symbol, m->curr_symbol());
588       c->_M_positive_sign_size
589         = __copy(c->_M_positive_sign, m->positive_sign());
590       c->_M_negative_sign_size
591         = __copy(c->_M_negative_sign, m->negative_sign());
592
593       c->_M_pos_format = m->pos_format();
594       c->_M_neg_format = m->neg_format();
595     }
596
597   template void
598   __moneypunct_fill_cache(current_abi, const facet*,
599                           __moneypunct_cache<char, true>*);
600
601   template void
602   __moneypunct_fill_cache(current_abi, const facet*,
603                           __moneypunct_cache<char, false>*);
604
605 #ifdef _GLIBCXX_USE_WCHAR_T
606   template void
607   __moneypunct_fill_cache(current_abi, const facet*,
608                           __moneypunct_cache<wchar_t, true>*);
609
610   template void
611   __moneypunct_fill_cache(current_abi, const facet*,
612                           __moneypunct_cache<wchar_t, false>*);
613 #endif
614
615   template<typename C>
616     messages_base::catalog
617     __messages_open(current_abi, const facet* f, const char* s, size_t n,
618                     const locale& l)
619     {
620       auto* m = static_cast<const messages<C>*>(f);
621       string str(s, n);
622       return m->open(str, l);
623     }
624
625   template messages_base::catalog
626   __messages_open<char>(current_abi, const facet*, const char*, size_t,
627                         const locale&);
628
629 #ifdef _GLIBCXX_USE_WCHAR_T
630   template messages_base::catalog
631   __messages_open<wchar_t>(current_abi, const facet*, const char*, size_t,
632                            const locale&);
633 #endif
634
635   template<typename C>
636     void
637     __messages_get(current_abi, const facet* f, __any_string& st,
638                    messages_base::catalog c, int set, int msgid,
639                    const C* s, size_t n)
640     {
641       auto* m = static_cast<const messages<C>*>(f);
642       st = m->get(c, set, msgid, basic_string<C>(s, n));
643     }
644
645   template void
646   __messages_get(current_abi, const facet*, __any_string&,
647                  messages_base::catalog, int, int, const char*, size_t);
648
649 #ifdef _GLIBCXX_USE_WCHAR_T
650   template void
651   __messages_get(current_abi, const facet*, __any_string&,
652                  messages_base::catalog, int, int, const wchar_t*, size_t);
653 #endif
654
655   template<typename C>
656     void
657     __messages_close(current_abi, const facet* f, messages_base::catalog c)
658     {
659       static_cast<const messages<C>*>(f)->close(c);
660     }
661
662   template void
663   __messages_close<char>(current_abi, const facet*, messages_base::catalog c);
664
665 #ifdef _GLIBCXX_USE_WCHAR_T
666   template void
667   __messages_close<wchar_t>(current_abi, const facet*,
668                             messages_base::catalog c);
669 #endif
670
671   template<typename C>
672     time_base::dateorder
673     __time_get_dateorder(current_abi, const facet* f)
674     { return static_cast<const time_get<C>*>(f)->date_order(); }
675
676   template time_base::dateorder
677   __time_get_dateorder<char>(current_abi, const facet*);
678
679 #ifdef _GLIBCXX_USE_WCHAR_T
680   template time_base::dateorder
681   __time_get_dateorder<wchar_t>(current_abi, const facet*);
682 #endif
683
684   template<typename C>
685     istreambuf_iterator<C>
686     __time_get(current_abi, const facet* f,
687                istreambuf_iterator<C> beg, istreambuf_iterator<C> end,
688                ios_base& io, ios_base::iostate& err, tm* t, char which)
689     {
690       auto* g = static_cast<const time_get<C>*>(f);
691       switch(which)
692       {
693       case 't':
694         return g->get_time(beg, end, io, err, t);
695       case 'd':
696         return g->get_date(beg, end, io, err, t);
697       case 'w':
698         return g->get_weekday(beg, end, io, err, t);
699       case 'm':
700         return g->get_monthname(beg, end, io, err, t);
701       case 'y':
702         return g->get_year(beg, end, io, err, t);
703       default:
704         __builtin_unreachable();
705       }
706     }
707
708   template istreambuf_iterator<char>
709   __time_get(current_abi, const facet*,
710              istreambuf_iterator<char>, istreambuf_iterator<char>,
711              ios_base&, ios_base::iostate&, tm*, char);
712
713 #ifdef _GLIBCXX_USE_WCHAR_T
714   template istreambuf_iterator<wchar_t>
715   __time_get(current_abi, const facet*,
716              istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
717              ios_base&, ios_base::iostate&, tm*, char);
718 #endif
719
720   template<typename C>
721     istreambuf_iterator<C>
722     __money_get(current_abi, const facet* f,
723                 istreambuf_iterator<C> s, istreambuf_iterator<C> end,
724                 bool intl, ios_base& str, ios_base::iostate& err,
725                 long double* units, __any_string* digits)
726     {
727       auto* m = static_cast<const money_get<C>*>(f);
728       if (units)
729         return m->get(s, end, intl, str, err, *units);
730       basic_string<C> digits2;
731       s = m->get(s, end, intl, str, err, digits2);
732       if (err == ios_base::goodbit)
733         *digits = digits2;
734       return s;
735     }
736
737   template istreambuf_iterator<char>
738   __money_get(current_abi, const facet*,
739               istreambuf_iterator<char>, istreambuf_iterator<char>,
740               bool, ios_base&, ios_base::iostate&,
741               long double*, __any_string*);
742
743 #ifdef _GLIBCXX_USE_WCHAR_T
744   template istreambuf_iterator<wchar_t>
745   __money_get(current_abi, const facet*,
746               istreambuf_iterator<wchar_t>, istreambuf_iterator<wchar_t>,
747               bool, ios_base&, ios_base::iostate&,
748               long double*, __any_string*);
749 #endif
750
751   template<typename C>
752     ostreambuf_iterator<C>
753     __money_put(current_abi, const facet* f, ostreambuf_iterator<C> s,
754                 bool intl, ios_base& io, C fill, long double units,
755                 const __any_string* digits)
756     {
757       auto* m = static_cast<const money_put<C>*>(f);
758       if (digits)
759         return m->put(s, intl, io, fill, *digits);
760       else
761         return m->put(s, intl, io, fill, units);
762     }
763
764   template ostreambuf_iterator<char>
765   __money_put(current_abi, const facet*, ostreambuf_iterator<char>,
766                 bool, ios_base&, char, long double, const __any_string*);
767
768 #ifdef _GLIBCXX_USE_WCHAR_T
769   template ostreambuf_iterator<wchar_t>
770   __money_put(current_abi, const facet*, ostreambuf_iterator<wchar_t>,
771                 bool, ios_base&, wchar_t, long double, const __any_string*);
772 #endif
773
774 _GLIBCXX_END_NAMESPACE_VERSION
775 } // namespace __facet_shims
776
777 _GLIBCXX_BEGIN_NAMESPACE_VERSION
778   // Create a new shim facet of type WHICH that forwards calls to F.
779   // F is the replacement facet provided by the user, WHICH is the ID of
780   // F's "other ABI twin" which we are replacing with a shim.
781   const locale::facet*
782 #if _GLIBCXX_USE_CXX11_ABI
783   locale::facet::_M_sso_shim(const locale::id* which) const
784 #else
785   locale::facet::_M_cow_shim(const locale::id* which) const
786 #endif
787   {
788     using namespace __facet_shims;
789
790 #if __cpp_rtti
791     // If this is already a shim just use its underlying facet.
792     if (auto* p = dynamic_cast<const __shim*>(this))
793       return p->_M_get();
794 #endif
795
796     if (which == &numpunct<char>::id)
797       return new numpunct_shim<char>{this};
798     if (which == &std::collate<char>::id)
799       return new collate_shim<char>{this};
800     if (which == &time_get<char>::id)
801       return new time_get_shim<char>{this};
802     if (which == &money_get<char>::id)
803       return new money_get_shim<char>{this};
804     if (which == &money_put<char>::id)
805       return new money_put_shim<char>{this};
806     if (which == &moneypunct<char, true>::id)
807       return new moneypunct_shim<char, true>{this};
808     if (which == &moneypunct<char, false>::id)
809       return new moneypunct_shim<char, false>{this};
810     if (which == &std::messages<char>::id)
811       return new messages_shim<char>{this};
812 #ifdef _GLIBCXX_USE_WCHAR_T
813     if (which == &numpunct<wchar_t>::id)
814       return new numpunct_shim<wchar_t>{this};
815     if (which == &std::collate<wchar_t>::id)
816       return new collate_shim<wchar_t>{this};
817     if (which == &time_get<wchar_t>::id)
818       return new time_get_shim<wchar_t>{this};
819     if (which == &money_get<wchar_t>::id)
820       return new money_get_shim<wchar_t>{this};
821     if (which == &money_put<wchar_t>::id)
822       return new money_put_shim<wchar_t>{this};
823     if (which == &moneypunct<wchar_t, true>::id)
824       return new moneypunct_shim<wchar_t, true>{this};
825     if (which == &moneypunct<wchar_t, false>::id)
826       return new moneypunct_shim<wchar_t, false>{this};
827     if (which == &std::messages<wchar_t>::id)
828       return new messages_shim<wchar_t>{this};
829 #endif
830     __throw_logic_error("cannot create shim for unknown locale::facet");
831   }
832
833 _GLIBCXX_END_NAMESPACE_VERSION
834 } // namespace std