c++: ICE on invalid with NSDMI in C++98 [PR98352]
[official-gcc.git] / libcody / internal.hh
blob8901629cddbf7078e8f8fd86656328dd3357bbc1
1 // CODYlib -*- mode:c++ -*-
2 // Copyright (C) 2020 Nathan Sidwell, nathan@acm.org
3 // License: Apache v2.0
5 #include "cody.hh"
7 #ifndef __has_builtin
8 #define __has_builtin(X) 0
9 #endif
10 #ifndef __has_include
11 #define __has_include(X) 0
12 #endif
14 // C++
15 #if __has_builtin(__builtin_FILE) && __has_builtin(__builtin_LINE)
16 #define CODY_LOC_BUILTIN 1
17 #elif __has_include (<source_location>)
18 #include <source_location>
19 #ifdef __cpp_lib_source_location
20 #define CODY_LOC_SOURCE 1
21 #endif
22 #endif
24 // C
25 #include <cstdio>
27 namespace Cody {
29 // Location is needed regardless of checking, to make the fatal
30 // handler simpler
31 class Location
33 protected:
34 char const *file;
35 unsigned line;
37 public:
38 constexpr Location (char const *file_
39 #if CODY_LOC_BUILTIN
40 = __builtin_FILE ()
41 #elif !CODY_LOC_SOURCE
42 = nullptr
43 #endif
44 , unsigned line_
45 #if CODY_LOC_BUILTIN
46 = __builtin_LINE ()
47 #elif !CODY_LOC_SOURCE
48 = 0
49 #endif
51 :file (file_), line (line_)
55 #if !CODY_LOC_BUILTIN && CODY_LOC_SOURCE
56 using source_location = std::source_location;
58 constexpr Location (source_location loc = source_location::current ())
59 : Location (loc.file (), loc.line ())
62 #endif
64 public:
65 constexpr char const *File () const
67 return file;
69 constexpr unsigned Line () const
71 return line;
75 void HCF [[noreturn]]
77 char const *msg
78 #if NMS_CHECKING
79 , Location const = Location ()
80 #if !CODY_LOC_BUILTIN && !CODY_LOC_SOURCE
81 #define HCF(M) HCF ((M), Cody::Location (__FILE__, __LINE__))
82 #endif
83 #endif
84 ) noexcept;
86 #if NMS_CHECKING
87 void AssertFailed [[noreturn]] (Location loc = Location ()) noexcept;
88 void Unreachable [[noreturn]] (Location loc = Location ()) noexcept;
89 #if !CODY_LOC_BUILTIN && !CODY_LOC_SOURCE
90 #define AssertFailed() AssertFailed (Cody::Location (__FILE__, __LINE__))
91 #define Unreachable() Unreachable (Cody::Location (__FILE__, __LINE__))
92 #endif
94 // Do we have __VA_OPT__, alas no specific feature macro for it :(
95 // From stack overflow
96 // https://stackoverflow.com/questions/48045470/portably-detect-va-opt-support
97 // Relies on having variadic macros, but they're a C++11 thing, so
98 // we're good
99 #define HAVE_ARG_3(a,b,c,...) c
100 #define HAVE_VA_OPT_(...) HAVE_ARG_3(__VA_OPT__(,),true,false,)
101 #define HAVE_VA_OPT HAVE_VA_OPT_(?)
103 // Oh, for lazily evaluated function parameters
104 #if HAVE_VA_OPT
105 // Assert is variadic, so you can write Assert (TPL<A,B>(C)) without
106 // extraneous parens. I don't think we need that though.
107 #define Assert(EXPR, ...) \
108 (__builtin_expect (bool (EXPR __VA_OPT__ (, __VA_ARGS__)), true) \
109 ? (void)0 : AssertFailed ())
110 #else
111 // If you don't have the GNU ,##__VA_ARGS__ pasting extension, we'll
112 // need another fallback
113 #define Assert(EXPR, ...) \
114 (__builtin_expect (bool (EXPR, ##__VA_ARGS__), true) \
115 ? (void)0 : AssertFailed ())
116 #endif
117 #else
118 // Not asserting, use EXPR in an unevaluated context
119 #if HAVE_VA_OPT
120 #define Assert(EXPR, ...) \
121 ((void)sizeof (bool (EXPR __VA_OPT__ (, __VA_ARGS__))), (void)0)
122 #else
123 #define Assert(EXPR, ...) \
124 ((void)sizeof (bool (EXPR, ##__VA_ARGS__)), (void)0)
125 #endif
127 inline void Unreachable () noexcept
129 __builtin_unreachable ();
131 #endif