1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef frontend_ErrorReporter_h
8 #define frontend_ErrorReporter_h
10 #include "mozilla/Variant.h"
13 #include <stdarg.h> // for va_list
14 #include <stddef.h> // for size_t
15 #include <stdint.h> // for uint32_t
17 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin
18 #include "js/UniquePtr.h"
19 #include "vm/ErrorReporting.h" // ErrorMetadata, ReportCompile{Error,Warning}
22 class JS_PUBLIC_API ReadOnlyCompileOptions
;
28 // An interface class to provide strictMode getter method, which is used by
29 // ErrorReportMixin::strictModeError* methods.
31 // This class is separated to be used as a back-channel from TokenStream to the
32 // strict mode flag which is available inside Parser, to avoid exposing the
33 // rest of SharedContext to TokenStream.
34 class StrictModeGetter
{
36 virtual bool strictMode() const = 0;
39 // This class provides error reporting methods, including warning, extra
40 // warning, and strict mode error.
42 // A class that inherits this class must provide the following methods:
45 // * computeErrorMetadata
46 class ErrorReportMixin
: public StrictModeGetter
{
48 // Returns a compile options (extra warning, warning as error) for current
50 virtual const JS::ReadOnlyCompileOptions
& options() const = 0;
52 // Returns the current context.
53 virtual FrontendContext
* getContext() const = 0;
55 // A variant class for the offset of the error or warning.
58 using ErrorOffset
= mozilla::Variant
<uint32_t, Current
, NoOffset
>;
60 // Fills ErrorMetadata fields for an error or warning at given offset.
61 // * offset is uint32_t if methods ending with "At" is called
62 // * offset is NoOffset if methods ending with "NoOffset" is called
63 // * offset is Current otherwise
64 [[nodiscard
]] virtual bool computeErrorMetadata(
65 ErrorMetadata
* err
, const ErrorOffset
& offset
) const = 0;
71 // Methods ending with "At" are for an error at given offset.
72 // The offset is passed to computeErrorMetadata method and is transparent
75 // Methods ending with "NoOffset" are for an error that doesn't correspond
76 // to any offset. NoOffset is passed to computeErrorMetadata for them.
78 // Other methods except errorWithNotesAtVA are for an error at the current
79 // offset. Current is passed to computeErrorMetadata for them.
81 // Methods contains "WithNotes" can be used if there are error notes.
83 // errorWithNotesAtVA is the actual implementation for all of above.
84 // This can be called if the caller already has a va_list.
86 void error(unsigned errorNumber
, ...) const {
88 va_start(args
, errorNumber
);
90 errorWithNotesAtVA(nullptr, mozilla::AsVariant(Current()), errorNumber
,
95 void errorWithNotes(UniquePtr
<JSErrorNotes
> notes
, unsigned errorNumber
,
98 va_start(args
, errorNumber
);
100 errorWithNotesAtVA(std::move(notes
), mozilla::AsVariant(Current()),
105 void errorAt(uint32_t offset
, unsigned errorNumber
, ...) const {
107 va_start(args
, errorNumber
);
109 errorWithNotesAtVA(nullptr, mozilla::AsVariant(offset
), errorNumber
, &args
);
113 void errorWithNotesAt(UniquePtr
<JSErrorNotes
> notes
, uint32_t offset
,
114 unsigned errorNumber
, ...) const {
116 va_start(args
, errorNumber
);
118 errorWithNotesAtVA(std::move(notes
), mozilla::AsVariant(offset
),
123 void errorNoOffset(unsigned errorNumber
, ...) const {
125 va_start(args
, errorNumber
);
127 errorWithNotesAtVA(nullptr, mozilla::AsVariant(NoOffset()), errorNumber
,
132 void errorWithNotesNoOffset(UniquePtr
<JSErrorNotes
> notes
,
133 unsigned errorNumber
, ...) const {
135 va_start(args
, errorNumber
);
137 errorWithNotesAtVA(std::move(notes
), mozilla::AsVariant(NoOffset()),
142 void errorWithNotesAtVA(UniquePtr
<JSErrorNotes
> notes
,
143 const ErrorOffset
& offset
, unsigned errorNumber
,
144 va_list* args
) const {
145 ErrorMetadata metadata
;
146 if (!computeErrorMetadata(&metadata
, offset
)) {
150 ReportCompileErrorLatin1VA(getContext(), std::move(metadata
),
151 std::move(notes
), errorNumber
, args
);
156 // Reports a warning.
158 // Returns true if the warning is reported.
159 // Returns false if the warning is treated as an error, or an error occurs
162 // See the comment on the error section for details on what the arguments
163 // and function names indicate for all these functions.
165 [[nodiscard
]] bool warning(unsigned errorNumber
, ...) const {
167 va_start(args
, errorNumber
);
169 bool result
= warningWithNotesAtVA(nullptr, mozilla::AsVariant(Current()),
176 [[nodiscard
]] bool warningAt(uint32_t offset
, unsigned errorNumber
,
179 va_start(args
, errorNumber
);
181 bool result
= warningWithNotesAtVA(nullptr, mozilla::AsVariant(offset
),
188 [[nodiscard
]] bool warningNoOffset(unsigned errorNumber
, ...) const {
190 va_start(args
, errorNumber
);
192 bool result
= warningWithNotesAtVA(nullptr, mozilla::AsVariant(NoOffset()),
199 [[nodiscard
]] bool warningWithNotesAtVA(UniquePtr
<JSErrorNotes
> notes
,
200 const ErrorOffset
& offset
,
201 unsigned errorNumber
,
202 va_list* args
) const {
203 ErrorMetadata metadata
;
204 if (!computeErrorMetadata(&metadata
, offset
)) {
208 return compileWarning(std::move(metadata
), std::move(notes
), errorNumber
,
212 // ==== strictModeError ====
214 // Reports an error if in strict mode code, or warn if not.
216 // Returns true if not in strict mode and a warning is reported.
217 // Returns false if the error reported, or an error occurs while reporting.
219 // See the comment on the error section for details on what the arguments
220 // and function names indicate for all these functions.
222 [[nodiscard
]] bool strictModeError(unsigned errorNumber
, ...) const {
224 va_start(args
, errorNumber
);
226 bool result
= strictModeErrorWithNotesAtVA(
227 nullptr, mozilla::AsVariant(Current()), errorNumber
, &args
);
233 [[nodiscard
]] bool strictModeErrorWithNotes(UniquePtr
<JSErrorNotes
> notes
,
234 unsigned errorNumber
, ...) const {
236 va_start(args
, errorNumber
);
238 bool result
= strictModeErrorWithNotesAtVA(
239 std::move(notes
), mozilla::AsVariant(Current()), errorNumber
, &args
);
245 [[nodiscard
]] bool strictModeErrorAt(uint32_t offset
, unsigned errorNumber
,
248 va_start(args
, errorNumber
);
250 bool result
= strictModeErrorWithNotesAtVA(
251 nullptr, mozilla::AsVariant(offset
), errorNumber
, &args
);
257 [[nodiscard
]] bool strictModeErrorWithNotesAt(UniquePtr
<JSErrorNotes
> notes
,
259 unsigned errorNumber
,
262 va_start(args
, errorNumber
);
264 bool result
= strictModeErrorWithNotesAtVA(
265 std::move(notes
), mozilla::AsVariant(offset
), errorNumber
, &args
);
271 [[nodiscard
]] bool strictModeErrorNoOffset(unsigned errorNumber
, ...) const {
273 va_start(args
, errorNumber
);
275 bool result
= strictModeErrorWithNotesAtVA(
276 nullptr, mozilla::AsVariant(NoOffset()), errorNumber
, &args
);
282 [[nodiscard
]] bool strictModeErrorWithNotesNoOffset(
283 UniquePtr
<JSErrorNotes
> notes
, unsigned errorNumber
, ...) const {
285 va_start(args
, errorNumber
);
287 bool result
= strictModeErrorWithNotesAtVA(
288 std::move(notes
), mozilla::AsVariant(NoOffset()), errorNumber
, &args
);
294 [[nodiscard
]] bool strictModeErrorWithNotesAtVA(UniquePtr
<JSErrorNotes
> notes
,
295 const ErrorOffset
& offset
,
296 unsigned errorNumber
,
297 va_list* args
) const {
302 ErrorMetadata metadata
;
303 if (!computeErrorMetadata(&metadata
, offset
)) {
307 ReportCompileErrorLatin1VA(getContext(), std::move(metadata
),
308 std::move(notes
), errorNumber
, args
);
312 // Reports a warning, or an error if the warning is treated as an error.
313 [[nodiscard
]] bool compileWarning(ErrorMetadata
&& metadata
,
314 UniquePtr
<JSErrorNotes
> notes
,
315 unsigned errorNumber
, va_list* args
) const {
316 return ReportCompileWarning(getContext(), std::move(metadata
),
317 std::move(notes
), errorNumber
, args
);
321 // An interface class to provide miscellaneous methods used by error reporting
322 // etc. They're mostly used by BytecodeCompiler, BytecodeEmitter, and helper
323 // classes for emitter.
324 class ErrorReporter
: public ErrorReportMixin
{
326 // Returns Some(true) if the given offset is inside the given line
327 // number `lineNum`, or Some(false) otherwise.
329 // Return None if an error happens. This method itself doesn't report an
330 // error, and any failure is supposed to be reported as OOM in the caller.
331 virtual std::optional
<bool> isOnThisLine(size_t offset
,
332 uint32_t lineNum
) const = 0;
334 // Returns the line number for given offset.
335 virtual uint32_t lineAt(size_t offset
) const = 0;
337 // Returns the column number for given offset.
338 virtual JS::LimitedColumnNumberOneOrigin
columnAt(size_t offset
) const = 0;
341 } // namespace frontend
344 #endif // frontend_ErrorReporter_h