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 // UNSUPPORTED: no-exceptions
10
11 // The fix for issue 57964 requires an updated dylib due to explicit
12 // instantiations. That means Apple backdeployment targets remain broken.
13 // UNSUPPORTED: using-built-library-before-llvm-19
14
15 // <ios>
16
17 // class ios_base
18
19 // ~ios_base()
20 //
21 // Destroying a constructed ios_base object that has not been
22 // initialized by basic_ios::init is undefined behaviour. This can
23 // happen in practice, make sure the undefined behaviour is handled
24 // gracefully.
25 //
26 //
27 // [ios.base.cons]/1
28 //
29 // ios_base();
30 // Effects: Each ios_base member has an indeterminate value after construction.
31 // The object's members shall be initialized by calling basic_ios::init before
32 // the object's first use or before it is destroyed, whichever comes first;
33 // otherwise the behavior is undefined.
34 //
35 // [basic.ios.cons]/2
36 //
37 // basic_ios();
38 // Effects: Leaves its member objects uninitialized. The object shall be
39 // initialized by calling basic_ios::init before its first use or before it is
40 // destroyed, whichever comes first; otherwise the behavior is undefined.
41 //
42 // ostream and friends have a basic_ios virtual base.
43 // [class.base.init]/13
44 // In a non-delegating constructor, initialization proceeds in the
45 // following order:
46 // - First, and only for the constructor of the most derived class
47 // ([intro.object]), virtual base classes are initialized ...
48 //
49 // So in this example
50 // struct Foo : AlwaysThrows, std::ostream {
51 // Foo() : AlwaysThrows{}, std::ostream{nullptr} {}
52 // };
53 //
54 // Here
55 // - the ios_base object is constructed
56 // - the AlwaysThrows object is constructed and throws an exception
57 // - the AlwaysThrows object is destrodyed
58 // - the ios_base object is destroyed
59 //
60 // The ios_base object is destroyed before it has been initialized and runs
61 // into undefined behavior. By using __loc_ as a sentinel we can avoid
62 // accessing uninitialized memory in the destructor.
63
64 #include <ostream>
65
66 struct AlwaysThrows {
AlwaysThrowsAlwaysThrows67 AlwaysThrows() { throw 1; }
68 };
69
70 struct Foo : AlwaysThrows, std::ostream {
FooFoo71 Foo() : AlwaysThrows(), std::ostream(nullptr) {}
72 };
73
main(int,char **)74 int main(int, char**) {
75 try {
76 Foo foo;
77 } catch (...) {
78 };
79 return 0;
80 }
81