-
Notifications
You must be signed in to change notification settings - Fork 6
/
internal.hh
125 lines (111 loc) · 3.01 KB
/
internal.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// CODYlib -*- mode:c++ -*-
// Copyright (C) 2020 Nathan Sidwell, [email protected]
// License: Apache v2.0
#include "cody.hh"
// C++
#if __GNUC__ >= 10
#define CODY_LOC_BUILTIN 1
#elif !defined (__has_include)
#elif __has_include (<source_location>)
#include <source_location>
#define CODY_LOC_SOURCE 1
#endif
// C
#include <cstdio>
namespace Cody {
// Location is needed regardless of checking, to make the fatal
// handler simpler
class Location
{
protected:
char const *file;
unsigned line;
public:
constexpr Location (char const *file_
#if CODY_LOC_BUILTIN
= __builtin_FILE ()
#elif !CODY_LOC_SOURCE
= nullptr
#endif
, unsigned line_
#if CODY_LOC_BUILTIN
= __builtin_LINE ()
#elif !CODY_LOC_SOURCE
= 0
#endif
)
:file (file_), line (line_)
{
}
#if !CODY_LOC_BUILTIN && CODY_LOC_SOURCE
constexpr Location (source_location loc = source_location::current ())
: Location (loc.file (), loc.line ())
{
}
#endif
public:
constexpr char const *File () const
{
return file;
}
constexpr unsigned Line () const
{
return line;
}
};
void HCF [[noreturn]]
(
char const *msg
#if NMS_CHECKING
, Location const = Location ()
#if !CODY_LOC_BUILTIN && !CODY_LOC_SOURCE
#define HCF(M) HCF ((M), Cody::Location (__FILE__, __LINE__))
#endif
#endif
) noexcept;
#if NMS_CHECKING
void AssertFailed [[noreturn]] (Location loc = Location ()) noexcept;
void Unreachable [[noreturn]] (Location loc = Location ()) noexcept;
#if !CODY_LOC_BUILTIN && !CODY_LOC_SOURCE
#define AssertFailed() AssertFailed (Cody::Location (__FILE__, __LINE__))
#define Unreachable() Unreachable (Cody::Location (__FILE__, __LINE__))
#endif
// Do we have __VA_OPT__, alas no specific feature macro for it :(
// From stack overflow
// https://stackoverflow.com/questions/48045470/portably-detect-va-opt-support
// Relies on having variadic macros, but they're a C++11 thing, so
// we're good
#define HAVE_ARG_3(a,b,c,...) c
#define HAVE_VA_OPT_(...) HAVE_ARG_3(__VA_OPT__(,),true,false,)
#define HAVE_VA_OPT HAVE_VA_OPT_(?)
// Oh, for lazily evaluated function parameters
#if HAVE_VA_OPT
// Assert is variadic, so you can write Assert (TPL<A,B>(C)) without
// extraneous parens. I don't think we need that though.
#define Assert(EXPR, ...) \
(__builtin_expect (bool (EXPR __VA_OPT__ (, __VA_ARGS__)), true) \
? (void)0 : AssertFailed ())
#else
// If you don't have the GNU ,##__VA_ARGS__ pasting extension, we'll
// need another fallback
#define Assert(EXPR, ...) \
(__builtin_expect (bool (EXPR, ##__VA_ARGS__), true) \
? (void)0 : AssertFailed ())
#endif
#else
// Not asserting, use EXPR in an unevaluated context
#if HAVE_VA_OPT
#define Assert(EXPR, ...) \
((void)sizeof (bool (EXPR __VA_OPT__ (, __VA_ARGS__))), (void)0)
#else
#define Assert(EXPR, ...) \
((void)sizeof (bool (EXPR, ##__VA_ARGS__)), (void)0)
#endif
inline void Unreachable () noexcept
{
__builtin_unreachable ();
}
#endif
// FIXME: This should be user visible in some way
void BuildNote (FILE *stream) noexcept;
}