xref: /llvm-project/libcxx/test/std/input.output/iostream.objects/init.pass.cpp (revision f4c1258d5633fcf06385ff3fd1f4bf57ab971964)
139faf428SLouis Dionne //===----------------------------------------------------------------------===//
239faf428SLouis Dionne //
339faf428SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
439faf428SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
539faf428SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
639faf428SLouis Dionne //
739faf428SLouis Dionne //===----------------------------------------------------------------------===//
839faf428SLouis Dionne 
939faf428SLouis Dionne // Make sure that the iostreams are initialized before everything else.
1039faf428SLouis Dionne // This has been an issue when statically linking libc++ in some contexts.
1139faf428SLouis Dionne // See https://llvm.org/PR28954 for details.
1239faf428SLouis Dionne //
1339faf428SLouis Dionne // This test works by checking that std::{cin,cout,cerr} is the same in a
1439faf428SLouis Dionne // static object constructor and in the main function. It dumps the memory of
1539faf428SLouis Dionne // each stream in the static object constructor and compares it with the memory
1639faf428SLouis Dionne // in the main function.
1739faf428SLouis Dionne //
1839faf428SLouis Dionne // The assumption is that if there are no uses of the stream object (such as
1939faf428SLouis Dionne // construction), then its memory must be the same. In the case where the test
2039faf428SLouis Dionne // "fails" and we are actually accessing an uninitialized object when we perform
2139faf428SLouis Dionne // the memcpy, the behavior is technically undefined (so the test could still
2239faf428SLouis Dionne // pass).
2339faf428SLouis Dionne 
2439faf428SLouis Dionne #include <cassert>
2539faf428SLouis Dionne #include <cstring>
2639faf428SLouis Dionne #include <iostream>
2739faf428SLouis Dionne 
28*f4c1258dSLouis Dionne #include "test_macros.h"
29*f4c1258dSLouis Dionne 
3039faf428SLouis Dionne struct Checker {
3139faf428SLouis Dionne     char *cerr_mem_dump;
3239faf428SLouis Dionne     char *cin_mem_dump;
3339faf428SLouis Dionne     char *cout_mem_dump;
3439faf428SLouis Dionne     char *clog_mem_dump;
3539faf428SLouis Dionne 
CheckerChecker3639faf428SLouis Dionne     Checker()
3739faf428SLouis Dionne         : cerr_mem_dump(new char[sizeof(std::cerr)])
3839faf428SLouis Dionne         , cin_mem_dump(new char[sizeof(std::cin)])
3939faf428SLouis Dionne         , cout_mem_dump(new char[sizeof(std::cout)])
4039faf428SLouis Dionne         , clog_mem_dump(new char[sizeof(std::clog)])
4139faf428SLouis Dionne      {
4239faf428SLouis Dionne         std::memcpy(cerr_mem_dump, (char*)&std::cerr, sizeof(std::cerr));
4339faf428SLouis Dionne         std::memcpy(cin_mem_dump, (char*)&std::cin, sizeof(std::cin));
4439faf428SLouis Dionne         std::memcpy(cout_mem_dump, (char*)&std::cout, sizeof(std::cout));
4539faf428SLouis Dionne         std::memcpy(clog_mem_dump, (char*)&std::clog, sizeof(std::clog));
4639faf428SLouis Dionne     }
4739faf428SLouis Dionne 
~CheckerChecker4839faf428SLouis Dionne     ~Checker() {
4939faf428SLouis Dionne         delete[] cerr_mem_dump;
5039faf428SLouis Dionne         delete[] cin_mem_dump;
5139faf428SLouis Dionne         delete[] cout_mem_dump;
5239faf428SLouis Dionne         delete[] clog_mem_dump;
53*f4c1258dSLouis Dionne     }
54*f4c1258dSLouis Dionne };
55*f4c1258dSLouis Dionne static Checker check;
5639faf428SLouis Dionne 
57*f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
58*f4c1258dSLouis Dionne struct WideChecker {
59*f4c1258dSLouis Dionne     char *wcerr_mem_dump;
60*f4c1258dSLouis Dionne     char *wcin_mem_dump;
61*f4c1258dSLouis Dionne     char *wcout_mem_dump;
62*f4c1258dSLouis Dionne     char *wclog_mem_dump;
63*f4c1258dSLouis Dionne 
WideCheckerWideChecker64*f4c1258dSLouis Dionne     WideChecker()
65*f4c1258dSLouis Dionne         : wcerr_mem_dump(new char[sizeof(std::wcerr)])
66*f4c1258dSLouis Dionne         , wcin_mem_dump(new char[sizeof(std::wcin)])
67*f4c1258dSLouis Dionne         , wcout_mem_dump(new char[sizeof(std::wcout)])
68*f4c1258dSLouis Dionne         , wclog_mem_dump(new char[sizeof(std::wclog)])
69*f4c1258dSLouis Dionne      {
70*f4c1258dSLouis Dionne         std::memcpy(wcerr_mem_dump, (char*)&std::wcerr, sizeof(std::wcerr));
71*f4c1258dSLouis Dionne         std::memcpy(wcin_mem_dump, (char*)&std::wcin, sizeof(std::wcin));
72*f4c1258dSLouis Dionne         std::memcpy(wcout_mem_dump, (char*)&std::wcout, sizeof(std::wcout));
73*f4c1258dSLouis Dionne         std::memcpy(wclog_mem_dump, (char*)&std::wclog, sizeof(std::wclog));
74*f4c1258dSLouis Dionne     }
75*f4c1258dSLouis Dionne 
~WideCheckerWideChecker76*f4c1258dSLouis Dionne     ~WideChecker() {
7739faf428SLouis Dionne         delete[] wcerr_mem_dump;
7839faf428SLouis Dionne         delete[] wcin_mem_dump;
7939faf428SLouis Dionne         delete[] wcout_mem_dump;
8039faf428SLouis Dionne         delete[] wclog_mem_dump;
8139faf428SLouis Dionne     }
8239faf428SLouis Dionne };
8339faf428SLouis Dionne 
84*f4c1258dSLouis Dionne static WideChecker wide_check;
85*f4c1258dSLouis Dionne #endif
8639faf428SLouis Dionne 
main(int,char **)87504bc07dSLouis Dionne int main(int, char**) {
8839faf428SLouis Dionne     assert(std::memcmp(check.cerr_mem_dump, (char const*)&std::cerr, sizeof(std::cerr)) == 0);
8939faf428SLouis Dionne     assert(std::memcmp(check.cin_mem_dump, (char const*)&std::cin, sizeof(std::cin)) == 0);
9039faf428SLouis Dionne     assert(std::memcmp(check.cout_mem_dump, (char const*)&std::cout, sizeof(std::cout)) == 0);
9139faf428SLouis Dionne     assert(std::memcmp(check.clog_mem_dump, (char const*)&std::clog, sizeof(std::clog)) == 0);
9239faf428SLouis Dionne 
93*f4c1258dSLouis Dionne #ifndef TEST_HAS_NO_WIDE_CHARACTERS
94*f4c1258dSLouis Dionne     assert(std::memcmp(wide_check.wcerr_mem_dump, (char const*)&std::wcerr, sizeof(std::wcerr)) == 0);
95*f4c1258dSLouis Dionne     assert(std::memcmp(wide_check.wcin_mem_dump, (char const*)&std::wcin, sizeof(std::wcin)) == 0);
96*f4c1258dSLouis Dionne     assert(std::memcmp(wide_check.wcout_mem_dump, (char const*)&std::wcout, sizeof(std::wcout)) == 0);
97*f4c1258dSLouis Dionne     assert(std::memcmp(wide_check.wclog_mem_dump, (char const*)&std::wclog, sizeof(std::wclog)) == 0);
98*f4c1258dSLouis Dionne #endif
99504bc07dSLouis Dionne     return 0;
10039faf428SLouis Dionne }
101