Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -55,6 +55,8 @@ option(LIBCXX_ENABLE_CXX1Y "Enable -std=c++1y and use of c++1y language features if the compiler supports it." OFF) option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON) option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON) +option(LIBCXX_ENABLE_STDIN "Build libc++ with support for stdin/std::cin." ON) +option(LIBCXX_ENABLE_STDOUT "Build libc++ with support for stdout/std::cout." ON) option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF) option(LIBCXX_ENABLE_MONOTONIC_CLOCK @@ -238,6 +240,16 @@ add_definitions(-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE) endif() +# LIBCXX_ENABLE_STDIN configuration +if (NOT LIBCXX_ENABLE_STDIN) + add_definitions(-D_LIBCPP_HAS_NO_STDIN) +endif() + +# LIBCXX_ENABLE_STDOUT configuration +if (NOT LIBCXX_ENABLE_STDOUT) + add_definitions(-D_LIBCPP_HAS_NO_STDOUT) +endif() + # LIBCXX_ENABLE_THREADS configuration if (NOT LIBCXX_ENABLE_THREADS) add_definitions(-D_LIBCPP_HAS_NO_THREADS) Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -732,6 +732,13 @@ #define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE #endif +// CloudABI is intended for running networked services. Processes do not +// have standard input and output channels. +#ifdef __CloudABI__ +#define _LIBCPP_HAS_NO_STDIN +#define _LIBCPP_HAS_NO_STDOUT +#endif + #if defined(__ANDROID__) || defined(__CloudABI__) #define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE #endif Index: include/cstdio =================================================================== --- include/cstdio +++ include/cstdio @@ -144,34 +144,20 @@ using ::fpos_t; using ::size_t; -#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE -using ::remove; -using ::rename; -using ::tmpfile; -using ::tmpnam; -#endif using ::fclose; using ::fflush; -#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE -using ::fopen; -using ::freopen; -#endif using ::setbuf; using ::setvbuf; using ::fprintf; using ::fscanf; -using ::printf; -using ::scanf; using ::snprintf; using ::sprintf; using ::sscanf; #ifndef _LIBCPP_MSVCRT using ::vfprintf; using ::vfscanf; -using ::vscanf; using ::vsscanf; #endif // _LIBCPP_MSVCRT -using ::vprintf; using ::vsnprintf; using ::vsprintf; using ::fgetc; @@ -179,13 +165,7 @@ using ::fputc; using ::fputs; using ::getc; -using ::getchar; -#if _LIBCPP_STD_VER <= 11 -using ::gets; -#endif using ::putc; -using ::putchar; -using ::puts; using ::ungetc; using ::fread; using ::fwrite; @@ -199,6 +179,31 @@ using ::ferror; using ::perror; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE +using ::fopen; +using ::freopen; +using ::remove; +using ::rename; +using ::tmpfile; +using ::tmpnam; +#endif + +#ifndef _LIBCPP_HAS_NO_STDIN +using ::getchar; +#if _LIBCPP_STD_VER <= 11 +using ::gets; +#endif +using ::scanf; +using ::vscanf; +#endif + +#ifndef _LIBCPP_HAS_NO_STDOUT +using ::printf; +using ::putchar; +using ::puts; +using ::vprintf; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CSTDIO Index: include/cwchar =================================================================== --- include/cwchar +++ include/cwchar @@ -126,24 +126,18 @@ using ::swprintf; using ::vfwprintf; using ::vswprintf; -using ::vwprintf; #ifndef _LIBCPP_MSVCRT using ::swscanf; using ::vfwscanf; using ::vswscanf; -using ::vwscanf; #endif // _LIBCPP_MSVCRT -using ::wprintf; -using ::wscanf; using ::fgetwc; using ::fgetws; using ::fputwc; using ::fputws; using ::fwide; using ::getwc; -using ::getwchar; using ::putwc; -using ::putwchar; using ::ungetwc; using ::wcstod; #ifndef _LIBCPP_MSVCRT @@ -212,6 +206,20 @@ using ::mbsrtowcs; using ::wcsrtombs; +#ifndef _LIBCPP_HAS_NO_STDIN +using ::getwchar; +#ifndef _LIBCPP_MSVCRT +using ::vwscanf; +#endif // _LIBCPP_MSVCRT +using ::wscanf; +#endif + +#ifndef _LIBCPP_HAS_NO_STDOUT +using ::putwchar; +using ::vwprintf; +using ::wprintf; +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP_CWCHAR Index: include/iostream =================================================================== --- include/iostream +++ include/iostream @@ -46,13 +46,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD +#ifndef _LIBCPP_HAS_NO_STDIN extern _LIBCPP_FUNC_VIS istream cin; -extern _LIBCPP_FUNC_VIS ostream cout; -extern _LIBCPP_FUNC_VIS ostream cerr; -extern _LIBCPP_FUNC_VIS ostream clog; extern _LIBCPP_FUNC_VIS wistream wcin; +#endif +#ifndef _LIBCPP_HAS_NO_STDOUT +extern _LIBCPP_FUNC_VIS ostream cout; extern _LIBCPP_FUNC_VIS wostream wcout; +#endif +extern _LIBCPP_FUNC_VIS ostream cerr; extern _LIBCPP_FUNC_VIS wostream wcerr; +extern _LIBCPP_FUNC_VIS ostream clog; extern _LIBCPP_FUNC_VIS wostream wclog; _LIBCPP_END_NAMESPACE_STD Index: src/iostream.cpp =================================================================== --- src/iostream.cpp +++ src/iostream.cpp @@ -13,55 +13,75 @@ _LIBCPP_BEGIN_NAMESPACE_STD -static mbstate_t state_types[6] = {}; - +#ifndef _LIBCPP_HAS_NO_STDIN +_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin [sizeof(istream)]; _ALIGNAS_TYPE (__stdinbuf ) static char __cin [sizeof(__stdinbuf )]; -_ALIGNAS_TYPE (__stdoutbuf) static char __cout[sizeof(__stdoutbuf)]; -_ALIGNAS_TYPE (__stdoutbuf) static char __cerr[sizeof(__stdoutbuf)]; +static mbstate_t mb_cin; +_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin [sizeof(wistream)]; _ALIGNAS_TYPE (__stdinbuf ) static char __wcin [sizeof(__stdinbuf )]; -_ALIGNAS_TYPE (__stdoutbuf) static char __wcout[sizeof(__stdoutbuf)]; -_ALIGNAS_TYPE (__stdoutbuf) static char __wcerr[sizeof(__stdoutbuf)]; +static mbstate_t mb_wcin; +#endif -_ALIGNAS_TYPE (istream) _LIBCPP_FUNC_VIS char cin [sizeof(istream)]; +#ifndef _LIBCPP_HAS_NO_STDOUT _ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cout[sizeof(ostream)]; -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)]; -_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)]; -_ALIGNAS_TYPE (wistream) _LIBCPP_FUNC_VIS char wcin [sizeof(wistream)]; +_ALIGNAS_TYPE (__stdoutbuf) static char __cout[sizeof(__stdoutbuf)]; +static mbstate_t mb_cout; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcout[sizeof(wostream)]; +_ALIGNAS_TYPE (__stdoutbuf) static char __wcout[sizeof(__stdoutbuf)]; +static mbstate_t mb_wcout; +#endif + +_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char cerr[sizeof(ostream)]; +_ALIGNAS_TYPE (__stdoutbuf) static char __cerr[sizeof(__stdoutbuf)]; +static mbstate_t mb_cerr; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wcerr[sizeof(wostream)]; +_ALIGNAS_TYPE (__stdoutbuf) static char __wcerr[sizeof(__stdoutbuf)]; +static mbstate_t mb_wcerr; + +_ALIGNAS_TYPE (ostream) _LIBCPP_FUNC_VIS char clog[sizeof(ostream)]; _ALIGNAS_TYPE (wostream) _LIBCPP_FUNC_VIS char wclog[sizeof(wostream)]; ios_base::Init __start_std_streams; ios_base::Init::Init() { - istream* cin_ptr = ::new(cin) istream(::new(__cin) __stdinbuf (stdin, state_types+0) ); - ostream* cout_ptr = ::new(cout) ostream(::new(__cout) __stdoutbuf(stdout, state_types+1)); - ostream* cerr_ptr = ::new(cerr) ostream(::new(__cerr) __stdoutbuf(stderr, state_types+2)); +#ifndef _LIBCPP_HAS_NO_STDIN + istream* cin_ptr = ::new(cin) istream(::new(__cin) __stdinbuf (stdin, &mb_cin)); + wistream* wcin_ptr = ::new(wcin) wistream(::new(__wcin) __stdinbuf (stdin, &mb_wcin)); +#endif +#ifndef _LIBCPP_HAS_NO_STDOUT + ostream* cout_ptr = ::new(cout) ostream(::new(__cout) __stdoutbuf(stdout, &mb_cout)); + wostream* wcout_ptr = ::new(wcout) wostream(::new(__wcout) __stdoutbuf(stdout, &mb_wcout)); +#endif + ostream* cerr_ptr = ::new(cerr) ostream(::new(__cerr) __stdoutbuf(stderr, &mb_cerr)); ::new(clog) ostream(cerr_ptr->rdbuf()); - cin_ptr->tie(cout_ptr); - _VSTD::unitbuf(*cerr_ptr); - cerr_ptr->tie(cout_ptr); - - wistream* wcin_ptr = ::new(wcin) wistream(::new(__wcin) __stdinbuf (stdin, state_types+3) ); - wostream* wcout_ptr = ::new(wcout) wostream(::new(__wcout) __stdoutbuf(stdout, state_types+4)); - wostream* wcerr_ptr = ::new(wcerr) wostream(::new(__wcerr) __stdoutbuf(stderr, state_types+5)); + wostream* wcerr_ptr = ::new(wcerr) wostream(::new(__wcerr) __stdoutbuf(stderr, &mb_wcerr)); ::new(wclog) wostream(wcerr_ptr->rdbuf()); + +#if !defined(_LIBCPP_HAS_NO_STDIN) && !defined(_LIBCPP_HAS_NO_STDOUT) + cin_ptr->tie(cout_ptr); wcin_ptr->tie(wcout_ptr); +#endif + _VSTD::unitbuf(*cerr_ptr); _VSTD::unitbuf(*wcerr_ptr); +#ifndef _LIBCPP_HAS_NO_STDOUT + cerr_ptr->tie(cout_ptr); wcerr_ptr->tie(wcout_ptr); +#endif } ios_base::Init::~Init() { +#ifndef _LIBCPP_HAS_NO_STDOUT ostream* cout_ptr = reinterpret_cast(cout); - ostream* clog_ptr = reinterpret_cast(clog); + wostream* wcout_ptr = reinterpret_cast(wcout); cout_ptr->flush(); - clog_ptr->flush(); + wcout_ptr->flush(); +#endif - wostream* wcout_ptr = reinterpret_cast(wcout); + ostream* clog_ptr = reinterpret_cast(clog); wostream* wclog_ptr = reinterpret_cast(wclog); - wcout_ptr->flush(); + clog_ptr->flush(); wclog_ptr->flush(); } Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -43,6 +43,8 @@ pythonize_bool(LIBCXX_ENABLE_SHARED) pythonize_bool(LIBCXX_BUILD_32_BITS) pythonize_bool(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE) + pythonize_bool(LIBCXX_ENABLE_STDIN) + pythonize_bool(LIBCXX_ENABLE_STDOUT) pythonize_bool(LIBCXX_ENABLE_THREADS) pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK) # The tests shouldn't link to any ABI library when it has been linked into Index: test/libcxx/test/config.py =================================================================== --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -348,6 +348,8 @@ self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() self.configure_compile_flags_no_global_filesystem_namespace() + self.configure_compile_flags_no_stdin() + self.configure_compile_flags_no_stdout() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] @@ -405,6 +407,18 @@ self.cxx.compile_flags += [ '-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE'] + def configure_compile_flags_no_stdin(self): + enable_stdin = self.get_lit_bool('enable_stdin', True) + if not enable_stdin: + self.config.available_features.add('libcpp-has-no-stdin') + self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDIN'] + + def configure_compile_flags_no_stdout(self): + enable_stdout = self.get_lit_bool('enable_stdout', True) + if not enable_stdout: + self.config.available_features.add('libcpp-has-no-stdout') + self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_STDOUT'] + def configure_compile_flags_no_threads(self): self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS'] self.config.available_features.add('libcpp-has-no-threads') Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -9,6 +9,8 @@ config.enable_shared = "@LIBCXX_ENABLE_SHARED@" config.enable_32bit = "@LIBCXX_BUILD_32_BITS@" config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE@" +config.enable_stdin = "@LIBCXX_ENABLE_STDIN@" +config.enable_stdout = "@LIBCXX_ENABLE_STDOUT@" config.enable_threads = "@LIBCXX_ENABLE_THREADS@" config.enable_monotonic_clock = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@" config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@" Index: test/std/input.output/file.streams/c.files/cstdio.pass.cpp =================================================================== --- test/std/input.output/file.streams/c.files/cstdio.pass.cpp +++ test/std/input.output/file.streams/c.files/cstdio.pass.cpp @@ -88,31 +88,17 @@ std::size_t s = 0; char* cp = 0; std::va_list va; -#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); -#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); -#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); -#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); @@ -121,13 +107,7 @@ static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); -#if _LIBCPP_STD_VER <= 11 - static_assert((std::is_same::value), ""); -#endif static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); @@ -140,4 +120,29 @@ static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); + +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); +#endif + +#ifndef _LIBCPP_HAS_NO_STDIN + static_assert((std::is_same::value), ""); +#if _LIBCPP_STD_VER <= 11 + static_assert((std::is_same::value), ""); +#endif + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); +#endif + +#ifndef _LIBCPP_HAS_NO_STDOUT + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); +#endif } Index: test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp +++ test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp @@ -19,7 +19,11 @@ #if 0 std::cerr << "Hello World!\n"; #else +#ifdef _LIBCPP_HAS_NO_STDOUT + assert(std::cerr.tie() == NULL); +#else assert(std::cerr.tie() == &std::cout); +#endif assert(std::cerr.flags() & std::ios_base::unitbuf); #endif // 0 } Index: test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp +++ test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-has-no-stdin + // // istream cin; @@ -23,6 +25,11 @@ std::cin >> i; std::cout << "The number is : " << i << '\n'; #else // 0 + (void)std::cin; +#ifdef _LIBCPP_HAS_NO_STDOUT + assert(std::cin.tie() == NULL); +#else assert(std::cin.tie() == &std::cout); #endif +#endif } Index: test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp +++ test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-has-no-stdout + // // istream cout; Index: test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp +++ test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp @@ -19,7 +19,11 @@ #if 0 std::wcerr << L"Hello World!\n"; #else +#ifdef _LIBCPP_HAS_NO_STDOUT + assert(std::wcerr.tie() == NULL); +#else assert(std::wcerr.tie() == &std::wcout); +#endif assert(std::wcerr.flags() & std::ios_base::unitbuf); #endif // 0 } Index: test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp +++ test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-has-no-stdin + // // istream wcin; @@ -23,6 +25,11 @@ std::wcin >> i; std::wcout << L"The number is : " << i << L'\n'; #else // 0 + (void)std::wcin; +#ifdef _LIBCPP_HAS_NO_STDOUT + assert(std::wcin.tie() == NULL); +#else assert(std::wcin.tie() == &std::wcout); #endif +#endif } Index: test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp =================================================================== --- test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp +++ test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +// XFAIL: libcpp-has-no-stdout + // // istream wcout; Index: test/std/strings/c.strings/cwchar.pass.cpp =================================================================== --- test/std/strings/c.strings/cwchar.pass.cpp +++ test/std/strings/c.strings/cwchar.pass.cpp @@ -50,19 +50,13 @@ static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); - static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); @@ -106,4 +100,16 @@ static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); + +#ifndef _LIBCPP_HAS_NO_STDIN + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); +#endif + +#ifndef _LIBCPP_HAS_NO_STDOUT + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); + static_assert((std::is_same::value), ""); +#endif }