Path: blob/main/system/lib/libcxx/src/iostream.cpp
6175 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "std_stream.h"910#include <__memory/construct_at.h>11#include <__ostream/basic_ostream.h>12#include <istream>1314#define ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)1516_LIBCPP_BEGIN_NAMESPACE_STD1718template <class StreamT, class BufferT>19union stream_data {20constexpr stream_data() {}21constexpr ~stream_data() {}22struct {23// The stream has to be the first element, since that's referenced by the stream declarations in <iostream>24StreamT stream;25BufferT buffer;26mbstate_t mb;27};2829void init(FILE* stdstream) {30mb = {};31std::construct_at(&buffer, stdstream, &mb);32std::construct_at(&stream, &buffer);33}34};3536#define CHAR_MANGLING_char "D"37#define CHAR_MANGLING_wchar_t "_W"38#define CHAR_MANGLING(CharT) CHAR_MANGLING_##CharT3940#ifdef _LIBCPP_COMPILER_CLANG_BASED41# define STRING_DATA_CONSTINIT constinit42#else43# define STRING_DATA_CONSTINIT44#endif4546#ifdef _LIBCPP_ABI_MICROSOFT47# define STREAM(StreamT, BufferT, CharT, var) \48STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var __asm__( \49"?" #var "@" ABI_NAMESPACE_STR "@std@@3V?$" #StreamT \50"@" CHAR_MANGLING(CharT) "U?$char_traits@" CHAR_MANGLING(CharT) "@" ABI_NAMESPACE_STR "@std@@@12@A")51#else52# define STREAM(StreamT, BufferT, CharT, var) STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var53#endif5455// These definitions and the declarations in <iostream> technically cause ODR violations, since they have different56// types (stream_data and {i,o}stream respectively). This means that <iostream> should never be included in this TU.5758_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, char, cin);59_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cout);60_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cerr);61_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, clog);62#if _LIBCPP_HAS_WIDE_CHARACTERS63_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, wchar_t, wcin);64_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcout);65_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcerr);66_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wclog);67#endif // _LIBCPP_HAS_WIDE_CHARACTERS6869// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority70// attribute with a value that's reserved for the implementation (we're the implementation).71#include "iostream_init.h"7273// On Windows the TLS storage for locales needs to be initialized before we create74// the standard streams, otherwise it may not be alive during program termination75// when we flush the streams.76static void force_locale_initialization() {77#if defined(_LIBCPP_MSVCRT_LIKE)78static bool once = []() {79auto loc = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);80{81__locale::__locale_guard g(loc); // forces initialization of locale TLS82((void)g);83}84__locale::__freelocale(loc);85return true;86}();87((void)once);88#endif89}9091class DoIOSInit {92public:93DoIOSInit();94~DoIOSInit();95};9697DoIOSInit::DoIOSInit() {98force_locale_initialization();99100cin.init(stdin);101cout.init(stdout);102cerr.init(stderr);103clog.init(stderr);104105cin.stream.tie(&cout.stream);106std::unitbuf(cerr.stream);107cerr.stream.tie(&cout.stream);108109#if _LIBCPP_HAS_WIDE_CHARACTERS110wcin.init(stdin);111wcout.init(stdout);112wcerr.init(stderr);113wclog.init(stderr);114115wcin.stream.tie(&wcout.stream);116std::unitbuf(wcerr.stream);117wcerr.stream.tie(&wcout.stream);118#endif119}120121DoIOSInit::~DoIOSInit() {122cout.stream.flush();123clog.stream.flush();124125#if _LIBCPP_HAS_WIDE_CHARACTERS126wcout.stream.flush();127wclog.stream.flush();128#endif129}130131ios_base::Init::Init() {132static DoIOSInit init_the_streams; // gets initialized once133}134135ios_base::Init::~Init() {}136137_LIBCPP_END_NAMESPACE_STD138139140