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 // Make sure that the iostreams are initialized before everything else. 10 // This has been an issue when statically linking libc++ in some contexts. 11 // See https://llvm.org/PR28954 for details. 12 // 13 // This test works by checking that std::{cin,cout,cerr} is the same in a 14 // static object constructor and in the main function. It dumps the memory of 15 // each stream in the static object constructor and compares it with the memory 16 // in the main function. 17 // 18 // The assumption is that if there are no uses of the stream object (such as 19 // construction), then its memory must be the same. In the case where the test 20 // "fails" and we are actually accessing an uninitialized object when we perform 21 // the memcpy, the behavior is technically undefined (so the test could still 22 // pass). 23 24 #include <cassert> 25 #include <cstring> 26 #include <iostream> 27 28 struct Checker { 29 char *cerr_mem_dump; 30 char *cin_mem_dump; 31 char *cout_mem_dump; 32 char *clog_mem_dump; 33 34 char *wcerr_mem_dump; 35 char *wcin_mem_dump; 36 char *wcout_mem_dump; 37 char *wclog_mem_dump; 38 39 Checker() 40 : cerr_mem_dump(new char[sizeof(std::cerr)]) 41 , cin_mem_dump(new char[sizeof(std::cin)]) 42 , cout_mem_dump(new char[sizeof(std::cout)]) 43 , clog_mem_dump(new char[sizeof(std::clog)]) 44 45 , wcerr_mem_dump(new char[sizeof(std::wcerr)]) 46 , wcin_mem_dump(new char[sizeof(std::wcin)]) 47 , wcout_mem_dump(new char[sizeof(std::wcout)]) 48 , wclog_mem_dump(new char[sizeof(std::wclog)]) 49 { 50 std::memcpy(cerr_mem_dump, (char*)&std::cerr, sizeof(std::cerr)); 51 std::memcpy(cin_mem_dump, (char*)&std::cin, sizeof(std::cin)); 52 std::memcpy(cout_mem_dump, (char*)&std::cout, sizeof(std::cout)); 53 std::memcpy(clog_mem_dump, (char*)&std::clog, sizeof(std::clog)); 54 55 std::memcpy(wcerr_mem_dump, (char*)&std::wcerr, sizeof(std::wcerr)); 56 std::memcpy(wcin_mem_dump, (char*)&std::wcin, sizeof(std::wcin)); 57 std::memcpy(wcout_mem_dump, (char*)&std::wcout, sizeof(std::wcout)); 58 std::memcpy(wclog_mem_dump, (char*)&std::wclog, sizeof(std::wclog)); 59 } 60 61 ~Checker() { 62 delete[] cerr_mem_dump; 63 delete[] cin_mem_dump; 64 delete[] cout_mem_dump; 65 delete[] clog_mem_dump; 66 67 delete[] wcerr_mem_dump; 68 delete[] wcin_mem_dump; 69 delete[] wcout_mem_dump; 70 delete[] wclog_mem_dump; 71 } 72 }; 73 74 static Checker check; 75 76 int main(int, char**) { 77 assert(std::memcmp(check.cerr_mem_dump, (char const*)&std::cerr, sizeof(std::cerr)) == 0); 78 assert(std::memcmp(check.cin_mem_dump, (char const*)&std::cin, sizeof(std::cin)) == 0); 79 assert(std::memcmp(check.cout_mem_dump, (char const*)&std::cout, sizeof(std::cout)) == 0); 80 assert(std::memcmp(check.clog_mem_dump, (char const*)&std::clog, sizeof(std::clog)) == 0); 81 82 assert(std::memcmp(check.wcerr_mem_dump, (char const*)&std::wcerr, sizeof(std::wcerr)) == 0); 83 assert(std::memcmp(check.wcin_mem_dump, (char const*)&std::wcin, sizeof(std::wcin)) == 0); 84 assert(std::memcmp(check.wcout_mem_dump, (char const*)&std::wcout, sizeof(std::wcout)) == 0); 85 assert(std::memcmp(check.wclog_mem_dump, (char const*)&std::wclog, sizeof(std::wclog)) == 0); 86 return 0; 87 } 88