Make the presence of stdin and stdout optional.

The idea behind Nuxi CloudABI is that it is targeted at (but not limited to)
running networked services in a sandboxed environment. The model behind stdin,
stdout and stderr is strongly focused on interactive tools in a command shell.
CloudABI does not support the notion of stdin and stdout, as 'standard
input/output' does not apply to services. The concept of stderr does makes
sense though, as services do need some mechanism to log error messages in a
uniform way.

This patch extends libc++ in such a way that std::cin and std::cout and the
associated <cstdio>/<cwchar> functions can be disabled through the flags
_LIBCPP_HAS_NO_STDIN and _LIBCPP_HAS_NO_STDOUT, respectively. At the same time
it attempts to clean up src/iostream.cpp a bit. Instead of using a single array
of mbstate_t objects and hardcoding the array indices, it creates separate
objects that declared next to the iostream objects and their buffers. The code
is also restructured by interleaving the construction and setup of c* and wc*
objects. That way it is more obvious that this is done identically.

The c* and wc* objects already have separate unit tests. Make use of this fact
by adding XFAILs in case libcpp-has-no-std* is set. That way the tests work in
both directions. If stdin or stdout is disabled, these tests will therefore
test for the absence of c* and wc*.

Differential Revision:	http://reviews.llvm.org/D8340


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@233275 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/std/input.output/file.streams/c.files/cstdio.pass.cpp b/test/std/input.output/file.streams/c.files/cstdio.pass.cpp
index 2ea09bc..ec4ad8a 100644
--- a/test/std/input.output/file.streams/c.files/cstdio.pass.cpp
+++ b/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<decltype(std::remove("")), int>::value), "");
-    static_assert((std::is_same<decltype(std::rename("","")), int>::value), "");
-    static_assert((std::is_same<decltype(std::tmpfile()), std::FILE*>::value), "");
-    static_assert((std::is_same<decltype(std::tmpnam(cp)), char*>::value), "");
-#endif
     static_assert((std::is_same<decltype(std::fclose(fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::fflush(fp)), int>::value), "");
-#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
-    static_assert((std::is_same<decltype(std::fopen("", "")), std::FILE*>::value), "");
-    static_assert((std::is_same<decltype(std::freopen("", "", fp)), std::FILE*>::value), "");
-#endif
     static_assert((std::is_same<decltype(std::setbuf(fp,cp)), void>::value), "");
     static_assert((std::is_same<decltype(std::vfprintf(fp,"",va)), int>::value), "");
     static_assert((std::is_same<decltype(std::fprintf(fp," ")), int>::value), "");
     static_assert((std::is_same<decltype(std::fscanf(fp,"")), int>::value), "");
-    static_assert((std::is_same<decltype(std::printf(" ")), int>::value), "");
-    static_assert((std::is_same<decltype(std::scanf(" ")), int>::value), "");
     static_assert((std::is_same<decltype(std::snprintf(cp,0," ")), int>::value), "");
     static_assert((std::is_same<decltype(std::sprintf(cp," ")), int>::value), "");
     static_assert((std::is_same<decltype(std::sscanf("","")), int>::value), "");
     static_assert((std::is_same<decltype(std::vfprintf(fp,"",va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vfscanf(fp,"",va)), int>::value), "");
-    static_assert((std::is_same<decltype(std::vprintf(" ",va)), int>::value), "");
-    static_assert((std::is_same<decltype(std::vscanf("",va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vsnprintf(cp,0," ",va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vsprintf(cp," ",va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vsscanf("","",va)), int>::value), "");
@@ -121,13 +107,7 @@
     static_assert((std::is_same<decltype(std::fputc(0,fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::fputs("",fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::getc(fp)), int>::value), "");
-    static_assert((std::is_same<decltype(std::getchar()), int>::value), "");
-#if _LIBCPP_STD_VER <= 11
-    static_assert((std::is_same<decltype(std::gets(cp)), char*>::value), "");
-#endif
     static_assert((std::is_same<decltype(std::putc(0,fp)), int>::value), "");
-    static_assert((std::is_same<decltype(std::putchar(0)), int>::value), "");
-    static_assert((std::is_same<decltype(std::puts("")), int>::value), "");
     static_assert((std::is_same<decltype(std::ungetc(0,fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::fread((void*)0,0,0,fp)), std::size_t>::value), "");
     static_assert((std::is_same<decltype(std::fwrite((const void*)0,0,0,fp)), std::size_t>::value), "");
@@ -140,4 +120,29 @@
     static_assert((std::is_same<decltype(std::feof(fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::ferror(fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::perror("")), void>::value), "");
+
+#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE
+    static_assert((std::is_same<decltype(std::fopen("", "")), std::FILE*>::value), "");
+    static_assert((std::is_same<decltype(std::freopen("", "", fp)), std::FILE*>::value), "");
+    static_assert((std::is_same<decltype(std::remove("")), int>::value), "");
+    static_assert((std::is_same<decltype(std::rename("","")), int>::value), "");
+    static_assert((std::is_same<decltype(std::tmpfile()), std::FILE*>::value), "");
+    static_assert((std::is_same<decltype(std::tmpnam(cp)), char*>::value), "");
+#endif
+
+#ifndef _LIBCPP_HAS_NO_STDIN
+    static_assert((std::is_same<decltype(std::getchar()), int>::value), "");
+#if _LIBCPP_STD_VER <= 11
+    static_assert((std::is_same<decltype(std::gets(cp)), char*>::value), "");
+#endif
+    static_assert((std::is_same<decltype(std::scanf(" ")), int>::value), "");
+    static_assert((std::is_same<decltype(std::vscanf("",va)), int>::value), "");
+#endif
+
+#ifndef _LIBCPP_HAS_NO_STDOUT
+    static_assert((std::is_same<decltype(std::printf(" ")), int>::value), "");
+    static_assert((std::is_same<decltype(std::putchar(0)), int>::value), "");
+    static_assert((std::is_same<decltype(std::puts("")), int>::value), "");
+    static_assert((std::is_same<decltype(std::vprintf(" ",va)), int>::value), "");
+#endif
 }
diff --git a/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp b/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp
index 9206d17..cdf53f8 100644
--- a/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.pass.cpp
+++ b/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
 }
diff --git a/test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp b/test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp
index 3481598..1ce04ff 100644
--- a/test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp
+++ b/test/std/input.output/iostream.objects/narrow.stream.objects/cin.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// XFAIL: libcpp-has-no-stdin
+
 // <iostream>
 
 // istream cin;
@@ -23,6 +25,10 @@
     std::cin >> i;
     std::cout << "The number is : " << i << '\n';
 #else  // 0
+#ifdef _LIBCPP_HAS_NO_STDOUT
+    assert(std::cin.tie() == NULL);
+#else
     assert(std::cin.tie() == &std::cout);
 #endif
+#endif
 }
diff --git a/test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp b/test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp
index 6000ae2..e5887e1 100644
--- a/test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp
+++ b/test/std/input.output/iostream.objects/narrow.stream.objects/cout.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// XFAIL: libcpp-has-no-stdout
+
 // <iostream>
 
 // istream cout;
diff --git a/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp b/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp
index 19a1dcd..b050781 100644
--- a/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.pass.cpp
+++ b/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
 }
diff --git a/test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp b/test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp
index 90a5668..6abd6af 100644
--- a/test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp
+++ b/test/std/input.output/iostream.objects/wide.stream.objects/wcin.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// XFAIL: libcpp-has-no-stdin
+
 // <iostream>
 
 // istream wcin;
@@ -23,6 +25,10 @@
     std::wcin >> i;
     std::wcout << L"The number is : " << i << L'\n';
 #else  // 0
+#ifdef _LIBCPP_HAS_NO_STDOUT
+    assert(std::wcin.tie() == NULL);
+#else
     assert(std::wcin.tie() == &std::wcout);
 #endif
+#endif
 }
diff --git a/test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp b/test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp
index 7a546aa..6543e0a 100644
--- a/test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp
+++ b/test/std/input.output/iostream.objects/wide.stream.objects/wcout.pass.cpp
@@ -7,6 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+// XFAIL: libcpp-has-no-stdout
+
 // <iostream>
 
 // istream wcout;
diff --git a/test/std/strings/c.strings/cwchar.pass.cpp b/test/std/strings/c.strings/cwchar.pass.cpp
index d0481b7..c3d868f 100644
--- a/test/std/strings/c.strings/cwchar.pass.cpp
+++ b/test/std/strings/c.strings/cwchar.pass.cpp
@@ -50,19 +50,13 @@
     static_assert((std::is_same<decltype(std::vfwscanf(fp, L"", va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vswprintf(ws, s, L"", va)), int>::value), "");
     static_assert((std::is_same<decltype(std::vswscanf(L"", L"", va)), int>::value), "");
-    static_assert((std::is_same<decltype(std::vwprintf(L"", va)), int>::value), "");
-    static_assert((std::is_same<decltype(std::vwscanf(L"", va)), int>::value), "");
-    static_assert((std::is_same<decltype(std::wprintf(L"")), int>::value), "");
-    static_assert((std::is_same<decltype(std::wscanf(L"")), int>::value), "");
     static_assert((std::is_same<decltype(std::fgetwc(fp)), std::wint_t>::value), "");
     static_assert((std::is_same<decltype(std::fgetws(ws, 0, fp)), wchar_t*>::value), "");
     static_assert((std::is_same<decltype(std::fputwc(L' ', fp)), std::wint_t>::value), "");
     static_assert((std::is_same<decltype(std::fputws(L"", fp)), int>::value), "");
     static_assert((std::is_same<decltype(std::fwide(fp, 0)), int>::value), "");
     static_assert((std::is_same<decltype(std::getwc(fp)), std::wint_t>::value), "");
-    static_assert((std::is_same<decltype(std::getwchar()), std::wint_t>::value), "");
     static_assert((std::is_same<decltype(std::putwc(L' ', fp)), std::wint_t>::value), "");
-    static_assert((std::is_same<decltype(std::putwchar(L' ')), std::wint_t>::value), "");
     static_assert((std::is_same<decltype(std::ungetwc(L' ', fp)), std::wint_t>::value), "");
     static_assert((std::is_same<decltype(std::wcstod(L"", (wchar_t**)0)), double>::value), "");
     static_assert((std::is_same<decltype(std::wcstof(L"", (wchar_t**)0)), float>::value), "");
@@ -106,4 +100,16 @@
     static_assert((std::is_same<decltype(std::wcrtomb(ns, L' ', &mb)), std::size_t>::value), "");
     static_assert((std::is_same<decltype(std::mbsrtowcs(ws, (const char**)0, s, &mb)), std::size_t>::value), "");
     static_assert((std::is_same<decltype(std::wcsrtombs(ns, (const wchar_t**)0, s, &mb)), std::size_t>::value), "");
+
+#ifndef _LIBCPP_HAS_NO_STDIN
+    static_assert((std::is_same<decltype(std::getwchar()), std::wint_t>::value), "");
+    static_assert((std::is_same<decltype(std::vwscanf(L"", va)), int>::value), "");
+    static_assert((std::is_same<decltype(std::wscanf(L"")), int>::value), "");
+#endif
+
+#ifndef _LIBCPP_HAS_NO_STDOUT
+    static_assert((std::is_same<decltype(std::putwchar(L' ')), std::wint_t>::value), "");
+    static_assert((std::is_same<decltype(std::vwprintf(L"", va)), int>::value), "");
+    static_assert((std::is_same<decltype(std::wprintf(L"")), int>::value), "");
+#endif
 }