13
13
#define MRDOX_REPORTER_HPP
14
14
15
15
#include < llvm/Support/Error.h>
16
+ #include < llvm/Support/Format.h>
16
17
#include < llvm/Support/Mutex.h>
17
18
#include < llvm/Support/raw_ostream.h>
18
19
#include < cassert>
19
- #include < new>
20
20
#include < source_location>
21
21
#include < string>
22
22
#include < string_view>
@@ -38,74 +38,79 @@ struct Reporter
38
38
{
39
39
/* * Return a suitable exit code.
40
40
*/
41
- int
42
- getExitCode () const noexcept
43
- {
44
- if (! failed_)
45
- return EXIT_SUCCESS;
46
- return EXIT_FAILURE;
47
- }
41
+ int getExitCode () const noexcept ;
42
+
43
+ /* * Print formatted output.
48
44
49
- /* * Report a non-successful Error
45
+ @param arg0, args The values to write.
50
46
*/
47
+ template <class Arg0 , class ... Args>
51
48
void
52
- failed (llvm::Error&& err);
49
+ print (
50
+ Arg0&& arg, Args&&... args);
53
51
54
52
/* * Report the failure of an action.
55
53
56
- @param action The operation which failed.
57
- @param e The object which holds the error.
58
- @param loc The location where the report is called.
54
+ @param arg0, args The values to write.
59
55
*/
60
- template <class E >
56
+ template <class Arg0 , class ... Args >
61
57
void
62
58
failed (
63
- llvm::StringRef action,
64
- E&& e,
65
- std::source_location const & loc =
66
- std::source_location::current ())
67
- {
68
- errs (action, " failed: " , std::move (e), " at " , loc);
69
- failed_ = true ;
70
- }
59
+ Arg0&& arg, Args&&... args);
71
60
72
- /* * Report a unit test failure .
61
+ /* * Return true and report a message if an error is indicated .
73
62
74
- @par Thread Safety
75
- May be called concurrently.
76
- */
77
- void
78
- testFailed ()
79
- {
80
- failed_ = true ;
81
- }
63
+ The error object `e` is inspected for a failure
64
+ condition. If `e` does not contain a failure,
65
+ then this function returns `false`. Otherwise
66
+ the function emits a diagnostic message to the
67
+ error channel and returns `true`.
82
68
83
- /* * Write a formatted string to outputs.
69
+ @par Output
70
+ The diagnostic message will always have the form:
71
+ @code
72
+ error: couldn't %1 because %2
73
+ @endcode
74
+ The first string is formed from the `actionFormat`
75
+ parameter and the variadic list of arguments,
76
+ while the second string is formed from the error
77
+ object.
84
78
85
- @par Thread Safety
86
- May be called concurrently.
79
+ If source location information is available, it
80
+ is reported on additional indented lines following
81
+ the diagnostic message.
82
+
83
+ @par Effects
84
+ The number of errors seen by the reporter
85
+ is incremented by one.
86
+
87
+ @return true if `e` indicates a failure.
88
+
89
+ @param e The error object to inspect.
90
+
91
+ @param arg0, args The values to write.
87
92
*/
88
- template <class ... Args>
89
- void
90
- outs (Args&&... args) const
91
- {
92
- llvm::StringRef s = format (std::forward<Args>(args)...);
93
- std::lock_guard<llvm::sys::Mutex> lock (m_);
94
- llvm::errs () << s << ' \n ' ;
95
- }
93
+ template <
94
+ class E ,
95
+ class Arg0 , class ... Args>
96
+ [[nodiscard]]
97
+ bool
98
+ error (
99
+ E&& e,
100
+ Arg0&& arg0,
101
+ Args&&... args);
96
102
97
- /* * Write a formatted string to errors.
103
+ // --------------------------------------------
104
+
105
+ /* * Report a unit test failure.
98
106
99
107
@par Thread Safety
100
108
May be called concurrently.
101
109
*/
102
- template <class ... Args>
103
110
void
104
- errs (Args&&... args) const
111
+ testFailed ()
105
112
{
106
- llvm::StringRef s = format (std::forward<Args>(args)...);
107
- std::lock_guard<llvm::sys::Mutex> lock (m_);
108
- llvm::errs () << s << ' \n ' ;
113
+ failed_ = true ;
109
114
}
110
115
111
116
static
@@ -114,94 +119,145 @@ struct Reporter
114
119
std::source_location const & loc);
115
120
116
121
private:
117
- /* * Return a string formatted from arguments.
122
+ // --------------------------------------------
118
123
119
- @par Thread Safety
120
- May be called concurrently.
121
- */
122
- template <class ... Args>
123
- llvm::StringRef
124
- format (
125
- Args&&... args) const
124
+ template <class T >
125
+ static bool isFailure (llvm::Expected<T>& e) noexcept
126
126
{
127
- static thread_local std::string temp;
128
- temp.clear ();
129
- llvm::raw_string_ostream os (temp);
130
- format_impl (os, std::forward<Args>(args)...);
131
- return llvm::StringRef (temp.data (), temp.size ());
127
+ return ! e.operator bool ();
132
128
}
133
129
134
- /* * Format arguments into an output stream.
135
- */
136
- template <class Arg0 , class ... Args>
137
- void
138
- format_impl (
139
- llvm::raw_string_ostream& os,
140
- Arg0&& arg0,
141
- Args&&... args) const
130
+ template <class T >
131
+ static bool isFailure (llvm::ErrorOr<T>& e) noexcept
142
132
{
143
- format_one (os, std::forward<Arg0>(arg0));
144
- if constexpr (sizeof ...(args) > 0 )
145
- format_impl (os, std::forward<Args>(args)...);
133
+ return ! e.operator bool ();
134
+ }
135
+
136
+ static bool isFailure (std::error_code const & ec) noexcept
137
+ {
138
+ return ec.operator bool ();
146
139
}
147
140
148
141
template <class T >
149
- void
150
- format_one (
151
- llvm::raw_string_ostream& os,
152
- T const & t) const
142
+ auto && nice(T&& t) const
153
143
{
154
- os << t ;
144
+ return std::forward<T>(t) ;
155
145
}
156
146
157
- void
158
- format_one (
159
- llvm::raw_string_ostream& os,
160
- std::error_code const & ec) const
147
+ template <class T >
148
+ auto nice (llvm::Expected<T>& e) const
161
149
{
162
- os << ec. message ( );
150
+ return nice (e. takeError () );
163
151
}
164
152
165
- void
166
- format_one (
167
- llvm::raw_string_ostream& os,
168
- llvm::Error&& err) const
153
+ template <class T >
154
+ auto nice (llvm::Expected<T>&& e) const
169
155
{
170
- // err.operator bool(); // VFALCO?
171
- os << toString (std::move (err));
156
+ return nice (e.takeError ());
172
157
}
173
158
174
159
template <class T >
175
- void
176
- format_one (
177
- llvm::raw_string_ostream& os,
178
- llvm::Expected<T>&& ex) const
160
+ auto nice (llvm::ErrorOr<T>& e) const
179
161
{
180
- format_one (os, ex .takeError ());
162
+ return nice (e .takeError ());
181
163
}
182
164
183
165
template <class T >
184
- void
185
- format_one (
186
- llvm::raw_string_ostream& os,
187
- llvm::ErrorOr<T>&& eor) const
166
+ auto nice (llvm::ErrorOr<T>&& e) const
188
167
{
189
- format_one (os, eor .getError ());
168
+ return nice (e .getError ());
190
169
}
191
170
192
- void
193
- format_one (
194
- llvm::raw_string_ostream& os,
195
- std::source_location const & loc) const
171
+ auto nice (std::error_code&& ec) const
196
172
{
197
- os << makeString (loc );
173
+ return ec. message ( );
198
174
}
199
175
176
+ auto nice (std::error_code const & ec) const
177
+ {
178
+ return ec.message ();
179
+ }
180
+
181
+ void
182
+ threadSafePrint (
183
+ llvm::raw_fd_ostream& os,
184
+ llvm::StringRef s,
185
+ std::size_t * n = nullptr );
186
+
187
+ static std::string& temp_string ();
188
+
200
189
private:
201
190
llvm::sys::Mutex mutable m_;
191
+ std::size_t errorCount_ = 0 ;
202
192
bool failed_ = false ;
203
193
};
204
194
195
+ // ------------------------------------------------
196
+
197
+ template <
198
+ class Arg0 , class ... Args>
199
+ void
200
+ Reporter::
201
+ print (
202
+ Arg0&& arg,
203
+ Args&&... args)
204
+ {
205
+ auto & temp = temp_string ();
206
+ temp.clear ();
207
+ {
208
+ llvm::raw_string_ostream os (temp);
209
+ os << std::forward<Arg0>(arg);
210
+ (os << ... << nice (std::forward<Args>(args)));
211
+ }
212
+ threadSafePrint (llvm::outs (), temp, nullptr );
213
+ }
214
+
215
+ template <
216
+ class Arg0 , class ... Args>
217
+ void
218
+ Reporter::
219
+ failed (
220
+ Arg0&& arg,
221
+ Args&&... args)
222
+ {
223
+ auto & temp = temp_string ();
224
+ temp.clear ();
225
+ {
226
+ llvm::raw_string_ostream os (temp);
227
+ os << " error: Couldn't " ;
228
+ os << std::forward<Arg0>(arg);
229
+ (os << ... << nice (std::forward<Args>(args)));
230
+ os << " ." ;
231
+ }
232
+ threadSafePrint (llvm::errs (), temp, &errorCount_);
233
+ }
234
+
235
+ template <
236
+ class E ,
237
+ class Arg0 , class ... Args>
238
+ bool
239
+ Reporter::
240
+ error (
241
+ E&& e,
242
+ Arg0&& arg,
243
+ Args&&... args)
244
+ {
245
+ if (! isFailure (e))
246
+ return false ;
247
+ auto & temp = temp_string ();
248
+ temp.clear ();
249
+ {
250
+ llvm::raw_string_ostream os (temp);
251
+ os << " error: Couldn't " ;
252
+ os << std::forward<Arg0>(arg);
253
+ (os << ... << nice (std::forward<Args>(args)));
254
+ os << " because " <<
255
+ nice (std::move (e)) << ' .' ;
256
+ }
257
+ threadSafePrint (llvm::errs (), temp, &errorCount_);
258
+ return true ;
259
+ }
260
+
205
261
} // mrdox
206
262
} // clang
207
263
0 commit comments