xref: /freebsd-src/contrib/llvm-project/libcxx/include/__chrono/exception.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric // -*- C++ -*-
2*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
3*0fca6ea1SDimitry Andric //
4*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*0fca6ea1SDimitry Andric //
8*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
9*0fca6ea1SDimitry Andric 
10*0fca6ea1SDimitry Andric // For information see https://libcxx.llvm.org/DesignDocs/TimeZone.html
11*0fca6ea1SDimitry Andric 
12*0fca6ea1SDimitry Andric #ifndef _LIBCPP___CHRONO_EXCEPTION_H
13*0fca6ea1SDimitry Andric #define _LIBCPP___CHRONO_EXCEPTION_H
14*0fca6ea1SDimitry Andric 
15*0fca6ea1SDimitry Andric #include <version>
16*0fca6ea1SDimitry Andric // Enable the contents of the header only when libc++ was built with experimental features enabled.
17*0fca6ea1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
18*0fca6ea1SDimitry Andric 
19*0fca6ea1SDimitry Andric #  include <__chrono/calendar.h>
20*0fca6ea1SDimitry Andric #  include <__chrono/local_info.h>
21*0fca6ea1SDimitry Andric #  include <__chrono/time_point.h>
22*0fca6ea1SDimitry Andric #  include <__config>
23*0fca6ea1SDimitry Andric #  include <__configuration/availability.h>
24*0fca6ea1SDimitry Andric #  include <__verbose_abort>
25*0fca6ea1SDimitry Andric #  include <format>
26*0fca6ea1SDimitry Andric #  include <stdexcept>
27*0fca6ea1SDimitry Andric #  include <string>
28*0fca6ea1SDimitry Andric 
29*0fca6ea1SDimitry Andric #  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30*0fca6ea1SDimitry Andric #    pragma GCC system_header
31*0fca6ea1SDimitry Andric #  endif
32*0fca6ea1SDimitry Andric 
33*0fca6ea1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
34*0fca6ea1SDimitry Andric 
35*0fca6ea1SDimitry Andric #  if _LIBCPP_STD_VER >= 20
36*0fca6ea1SDimitry Andric 
37*0fca6ea1SDimitry Andric namespace chrono {
38*0fca6ea1SDimitry Andric 
39*0fca6ea1SDimitry Andric class nonexistent_local_time : public runtime_error {
40*0fca6ea1SDimitry Andric public:
41*0fca6ea1SDimitry Andric   template <class _Duration>
42*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const local_time<_Duration>& __time, const local_info& __info)
43*0fca6ea1SDimitry Andric       : runtime_error{__create_message(__time, __info)} {
44*0fca6ea1SDimitry Andric     // [time.zone.exception.nonexist]/2
45*0fca6ea1SDimitry Andric     //   Preconditions: i.result == local_info::nonexistent is true.
46*0fca6ea1SDimitry Andric     // The value of __info.result is not used.
47*0fca6ea1SDimitry Andric     _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::nonexistent,
48*0fca6ea1SDimitry Andric                             "creating an nonexistent_local_time from a local_info that is not non-existent");
49*0fca6ea1SDimitry Andric   }
50*0fca6ea1SDimitry Andric 
51*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time(const nonexistent_local_time&)            = default;
52*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI nonexistent_local_time& operator=(const nonexistent_local_time&) = default;
53*0fca6ea1SDimitry Andric 
54*0fca6ea1SDimitry Andric   _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~nonexistent_local_time() override; // exported as key function
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric private:
57*0fca6ea1SDimitry Andric   template <class _Duration>
58*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {
59*0fca6ea1SDimitry Andric     return std::format(
60*0fca6ea1SDimitry Andric         R"({} is in a gap between
61*0fca6ea1SDimitry Andric {} {} and
62*0fca6ea1SDimitry Andric {} {} which are both equivalent to
63*0fca6ea1SDimitry Andric {} UTC)",
64*0fca6ea1SDimitry Andric         __time,
65*0fca6ea1SDimitry Andric         local_seconds{__info.first.end.time_since_epoch()} + __info.first.offset,
66*0fca6ea1SDimitry Andric         __info.first.abbrev,
67*0fca6ea1SDimitry Andric         local_seconds{__info.second.begin.time_since_epoch()} + __info.second.offset,
68*0fca6ea1SDimitry Andric         __info.second.abbrev,
69*0fca6ea1SDimitry Andric         __info.first.end);
70*0fca6ea1SDimitry Andric   }
71*0fca6ea1SDimitry Andric };
72*0fca6ea1SDimitry Andric 
73*0fca6ea1SDimitry Andric template <class _Duration>
74*0fca6ea1SDimitry Andric _LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_nonexistent_local_time(
75*0fca6ea1SDimitry Andric     [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) {
76*0fca6ea1SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
77*0fca6ea1SDimitry Andric   throw nonexistent_local_time(__time, __info);
78*0fca6ea1SDimitry Andric #    else
79*0fca6ea1SDimitry Andric   _LIBCPP_VERBOSE_ABORT("nonexistent_local_time was thrown in -fno-exceptions mode");
80*0fca6ea1SDimitry Andric #    endif
81*0fca6ea1SDimitry Andric }
82*0fca6ea1SDimitry Andric 
83*0fca6ea1SDimitry Andric class ambiguous_local_time : public runtime_error {
84*0fca6ea1SDimitry Andric public:
85*0fca6ea1SDimitry Andric   template <class _Duration>
86*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const local_time<_Duration>& __time, const local_info& __info)
87*0fca6ea1SDimitry Andric       : runtime_error{__create_message(__time, __info)} {
88*0fca6ea1SDimitry Andric     // [time.zone.exception.ambig]/2
89*0fca6ea1SDimitry Andric     //   Preconditions: i.result == local_info::ambiguous is true.
90*0fca6ea1SDimitry Andric     // The value of __info.result is not used.
91*0fca6ea1SDimitry Andric     _LIBCPP_ASSERT_PEDANTIC(__info.result == local_info::ambiguous,
92*0fca6ea1SDimitry Andric                             "creating an ambiguous_local_time from a local_info that is not ambiguous");
93*0fca6ea1SDimitry Andric   }
94*0fca6ea1SDimitry Andric 
95*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time(const ambiguous_local_time&)            = default;
96*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI ambiguous_local_time& operator=(const ambiguous_local_time&) = default;
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric   _LIBCPP_AVAILABILITY_TZDB _LIBCPP_EXPORTED_FROM_ABI ~ambiguous_local_time() override; // exported as key function
99*0fca6ea1SDimitry Andric 
100*0fca6ea1SDimitry Andric private:
101*0fca6ea1SDimitry Andric   template <class _Duration>
102*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI string __create_message(const local_time<_Duration>& __time, const local_info& __info) {
103*0fca6ea1SDimitry Andric     return std::format(
104*0fca6ea1SDimitry Andric         // There are two spaces after the full-stop; this has been verified
105*0fca6ea1SDimitry Andric         // in the sources of the Standard.
106*0fca6ea1SDimitry Andric         R"({0} is ambiguous.  It could be
107*0fca6ea1SDimitry Andric {0} {1} == {2} UTC or
108*0fca6ea1SDimitry Andric {0} {3} == {4} UTC)",
109*0fca6ea1SDimitry Andric         __time,
110*0fca6ea1SDimitry Andric         __info.first.abbrev,
111*0fca6ea1SDimitry Andric         __time - __info.first.offset,
112*0fca6ea1SDimitry Andric         __info.second.abbrev,
113*0fca6ea1SDimitry Andric         __time - __info.second.offset);
114*0fca6ea1SDimitry Andric   }
115*0fca6ea1SDimitry Andric };
116*0fca6ea1SDimitry Andric 
117*0fca6ea1SDimitry Andric template <class _Duration>
118*0fca6ea1SDimitry Andric _LIBCPP_NORETURN _LIBCPP_AVAILABILITY_TZDB _LIBCPP_HIDE_FROM_ABI void __throw_ambiguous_local_time(
119*0fca6ea1SDimitry Andric     [[maybe_unused]] const local_time<_Duration>& __time, [[maybe_unused]] const local_info& __info) {
120*0fca6ea1SDimitry Andric #    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
121*0fca6ea1SDimitry Andric   throw ambiguous_local_time(__time, __info);
122*0fca6ea1SDimitry Andric #    else
123*0fca6ea1SDimitry Andric   _LIBCPP_VERBOSE_ABORT("ambiguous_local_time was thrown in -fno-exceptions mode");
124*0fca6ea1SDimitry Andric #    endif
125*0fca6ea1SDimitry Andric }
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric } // namespace chrono
128*0fca6ea1SDimitry Andric 
129*0fca6ea1SDimitry Andric #  endif // _LIBCPP_STD_VER >= 20
130*0fca6ea1SDimitry Andric 
131*0fca6ea1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
132*0fca6ea1SDimitry Andric 
133*0fca6ea1SDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_TZDB)
134*0fca6ea1SDimitry Andric 
135*0fca6ea1SDimitry Andric #endif // _LIBCPP___CHRONO_EXCEPTION_H
136