1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "std_stream.h"
10
11#include <__memory/construct_at.h>
12#include <__ostream/basic_ostream.h>
13#include <istream>
14
15#define ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)
16
17_LIBCPP_BEGIN_NAMESPACE_STD
18
19template <class StreamT, class BufferT>
20union stream_data {
21 constexpr stream_data() {}
22 constexpr ~stream_data() {}
23 struct {
24 // The stream has to be the first element, since that's referenced by the stream declarations in <iostream>
25 StreamT stream;
26 BufferT buffer;
27 mbstate_t mb;
28 };
29
30 void init(FILE* stdstream) {
31 mb = {};
32 std::construct_at(&buffer, stdstream, &mb);
33 std::construct_at(&stream, &buffer);
34 }
35};
36
37#define CHAR_MANGLING_char "D"
38#define CHAR_MANGLING_wchar_t "_W"
39#define CHAR_MANGLING(CharT) CHAR_MANGLING_##CharT
40
41#ifdef _LIBCPP_COMPILER_CLANG_BASED
42# define STRING_DATA_CONSTINIT constinit
43#else
44# define STRING_DATA_CONSTINIT
45#endif
46
47#ifdef _LIBCPP_ABI_MICROSOFT
48# define STREAM(StreamT, BufferT, CharT, var) \
49 STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var __asm__( \
50 "?" #var "@" ABI_NAMESPACE_STR "@std@@3V?$" #StreamT \
51 "@" CHAR_MANGLING(CharT) "U?$char_traits@" CHAR_MANGLING(CharT) "@" ABI_NAMESPACE_STR "@std@@@12@A")
52#else
53# define STREAM(StreamT, BufferT, CharT, var) STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var
54#endif
55
56// These definitions and the declarations in <iostream> technically cause ODR violations, since they have different
57// types (stream_data and {i,o}stream respectively). This means that <iostream> should never be included in this TU.
58
59_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, char, cin);
60_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cout);
61_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cerr);
62_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, clog);
63#if _LIBCPP_HAS_WIDE_CHARACTERS
64_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, wchar_t, wcin);
65_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcout);
66_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcerr);
67_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wclog);
68#endif // _LIBCPP_HAS_WIDE_CHARACTERS
69
70// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
71// attribute with a value that's reserved for the implementation (we're the implementation).
72#include "iostream_init.h"
73
74// On Windows the TLS storage for locales needs to be initialized before we create
75// the standard streams, otherwise it may not be alive during program termination
76// when we flush the streams.
77static void force_locale_initialization() {
78#if defined(_LIBCPP_MSVCRT_LIKE)
79 static bool once = []() {
80 auto loc = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);
81 {
82 __locale::__locale_guard g(loc); // forces initialization of locale TLS
83 ((void)g);
84 }
85 __locale::__freelocale(loc);
86 return true;
87 }();
88 ((void)once);
89#endif
90}
91
92class DoIOSInit {
93public:
94 DoIOSInit();
95 ~DoIOSInit();
96};
97
98DoIOSInit::DoIOSInit() {
99 force_locale_initialization();
100
101 cin.init(stdin);
102 cout.init(stdout);
103 cerr.init(stderr);
104 clog.init(stderr);
105
106 cin.stream.tie(&cout.stream);
107 std::unitbuf(base&: cerr.stream);
108 cerr.stream.tie(&cout.stream);
109
110#if _LIBCPP_HAS_WIDE_CHARACTERS
111 wcin.init(stdin);
112 wcout.init(stdout);
113 wcerr.init(stderr);
114 wclog.init(stderr);
115
116 wcin.stream.tie(&wcout.stream);
117 std::unitbuf(wcerr.stream);
118 wcerr.stream.tie(&wcout.stream);
119#endif
120}
121
122DoIOSInit::~DoIOSInit() {
123 cout.stream.flush();
124 clog.stream.flush();
125
126#if _LIBCPP_HAS_WIDE_CHARACTERS
127 wcout.stream.flush();
128 wclog.stream.flush();
129#endif
130}
131
132ios_base::Init::Init() {
133 static DoIOSInit init_the_streams; // gets initialized once
134}
135
136ios_base::Init::~Init() {}
137
138_LIBCPP_END_NAMESPACE_STD
139

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of libcxx/src/iostream.cpp