aboutsummaryrefslogtreecommitdiff
path: root/gcc/d/dmd/errorsink.d
blob: 5793ef1c0e5e66e42f86d403bb04532d336c361c (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
 * Provides an abstraction for what to do with error messages.
 *
 * Copyright:   Copyright (C) 2023-2025 by The D Language Foundation, All Rights Reserved
 * Authors:     $(LINK2 https://www.digitalmars.com, Walter Bright)
 * License:     $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/compiler/src/dmd/errorsink.d, _errorsink.d)
 * Documentation:  https://dlang.org/phobos/dmd_errorsink.html
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/compiler/src/dmd/errorsink.d
 */

module dmd.errorsink;

import core.stdc.stdarg;

import dmd.location;

/***************************************
 * Where error/warning/deprecation messages go.
 */
abstract class ErrorSink
{
  nothrow:
  extern (C++):

    void verror(Loc loc, const(char)* format, va_list ap);
    void verrorSupplemental(Loc loc, const(char)* format, va_list ap);
    void vwarning(Loc loc, const(char)* format, va_list ap);
    void vwarningSupplemental(Loc loc, const(char)* format, va_list ap);
    void vmessage(Loc loc, const(char)* format, va_list ap);
    void vdeprecation(Loc loc, const(char)* format, va_list ap);
    void vdeprecationSupplemental(Loc loc, const(char)* format, va_list ap);

    void error(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        verror(loc, format, ap);
        va_end(ap);
    }

    void errorSupplemental(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        verrorSupplemental(loc, format, ap);
        va_end(ap);
    }

    void warning(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        vwarning(loc, format, ap);
        va_end(ap);
    }

    void warningSupplemental(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        vwarningSupplemental(loc, format, ap);
        va_end(ap);
    }

    void message(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        vmessage(loc, format, ap);
        va_end(ap);
    }

    void deprecation(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        vdeprecation(loc, format, ap);
        va_end(ap);
    }

    void deprecationSupplemental(Loc loc, const(char)* format, ...)
    {
        va_list ap;
        va_start(ap, format);
        vdeprecationSupplemental(loc, format, ap);
        va_end(ap);
    }

    /**
     * This will be called to indicate compilation has either
     * finished or terminated, no more errors are possible - it's
     * now the time to print any stored errors.
     *
     * The default implementation does nothing since most error sinks have no state
     */
    void plugSink() {}
}

/*****************************************
 * Just ignores the messages.
 */
class ErrorSinkNull : ErrorSink
{
  nothrow:
  extern (C++):
  override:

    void verror(Loc loc, const(char)* format, va_list ap) { }

    void verrorSupplemental(Loc loc, const(char)* format, va_list ap) { }

    void vwarning(Loc loc, const(char)* format, va_list ap) { }

    void vwarningSupplemental(Loc loc, const(char)* format, va_list ap) { }

    void vmessage(Loc loc, const(char)* format, va_list ap) { }

    void vdeprecation(Loc loc, const(char)* format, va_list ap) { }

    void vdeprecationSupplemental(Loc loc, const(char)* format, va_list ap) { }
}

/*****************************************
 * Ignores the messages, but sets `sawErrors` for any calls to `error()`
 */
class ErrorSinkLatch : ErrorSinkNull
{
  nothrow:
  extern (C++):
  override:

    bool sawErrors;

    void verror(Loc loc, const(char)* format, va_list ap) { sawErrors = true; }
}

/*****************************************
 * Simplest implementation, just sends messages to stderr.
 * See also: ErrorSinkCompiler.
 */
class ErrorSinkStderr : ErrorSink
{
    import core.stdc.stdio;
    import core.stdc.stdarg;

  nothrow:
  extern (C++):
  override:

    void verror(Loc loc, const(char)* format, va_list ap)
    {
        fputs("Error: ", stderr);
        const p = loc.toChars();
        if (*p)
        {
            fprintf(stderr, "%s: ", p);
            //mem.xfree(cast(void*)p); // loc should provide the free()
        }

        vfprintf(stderr, format, ap);
        fputc('\n', stderr);
    }

    void verrorSupplemental(Loc loc, const(char)* format, va_list ap) { }

    void vwarning(Loc loc, const(char)* format, va_list ap)
    {
        fputs("Warning: ", stderr);
        const p = loc.toChars();
        if (*p)
        {
            fprintf(stderr, "%s: ", p);
            //mem.xfree(cast(void*)p); // loc should provide the free()
        }

        vfprintf(stderr, format, ap);
        fputc('\n', stderr);
    }

    void vwarningSupplemental(Loc loc, const(char)* format, va_list ap) { }

    void vdeprecation(Loc loc, const(char)* format, va_list ap)
    {
        fputs("Deprecation: ", stderr);
        const p = loc.toChars();
        if (*p)
        {
            fprintf(stderr, "%s: ", p);
            //mem.xfree(cast(void*)p); // loc should provide the free()
        }

        vfprintf(stderr, format, ap);
        fputc('\n', stderr);
    }

    void vmessage(Loc loc, const(char)* format, va_list ap)
    {
        const p = loc.toChars();
        if (*p)
        {
            fprintf(stderr, "%s: ", p);
            //mem.xfree(cast(void*)p); // loc should provide the free()
        }

        vfprintf(stderr, format, ap);
        fputc('\n', stderr);
    }

    void vdeprecationSupplemental(Loc loc, const(char)* format, va_list ap) { }
}