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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- D I A G N O S T I C S . U T I L S --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2025, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
with Diagnostics.Repository; use Diagnostics.Repository;
with Diagnostics.Switch_Repository; use Diagnostics.Switch_Repository;
with Errout; use Errout;
with Erroutc; use Erroutc;
with Namet; use Namet;
with Opt; use Opt;
with Sinput; use Sinput;
with Sinfo.Nodes; use Sinfo.Nodes;
with Warnsw; use Warnsw;
package body Diagnostics.Utils is
------------------
-- Get_Human_Id --
------------------
function Get_Human_Id (D : Diagnostic_Type) return String_Ptr is
begin
if D.Switch = No_Switch_Id then
return Diagnostic_Entries (D.Id).Human_Id;
else
return Get_Switch (D).Human_Id;
end if;
end Get_Human_Id;
------------------
-- To_File_Name --
------------------
function To_File_Name (Sptr : Source_Ptr) return String is
Sfile : constant Source_File_Index := Get_Source_File_Index (Sptr);
Ref_Name : constant File_Name_Type :=
(if Full_Path_Name_For_Brief_Errors then Full_Ref_Name (Sfile)
else Reference_Name (Sfile));
begin
return Get_Name_String (Ref_Name);
end To_File_Name;
--------------------
-- Line_To_String --
--------------------
function Line_To_String (Sptr : Source_Ptr) return String is
Line : constant Logical_Line_Number := Get_Logical_Line_Number (Sptr);
Img_Raw : constant String := Int'Image (Int (Line));
begin
return Img_Raw (Img_Raw'First + 1 .. Img_Raw'Last);
end Line_To_String;
----------------------
-- Column_To_String --
----------------------
function Column_To_String (Sptr : Source_Ptr) return String is
Col : constant Column_Number := Get_Column_Number (Sptr);
Img_Raw : constant String := Int'Image (Int (Col));
begin
return
(if Col < 10 then "0" else "")
& Img_Raw (Img_Raw'First + 1 .. Img_Raw'Last);
end Column_To_String;
---------------
-- To_String --
---------------
function To_String (Sptr : Source_Ptr) return String is
begin
return
To_File_Name (Sptr) & ":" & Line_To_String (Sptr) & ":"
& Column_To_String (Sptr);
end To_String;
--------------------
-- Sloc_To_String --
--------------------
function Sloc_To_String
(N : Node_Or_Entity_Id; Ref : Source_Ptr) return String
is
begin
return Sloc_To_String (Sloc (N), Ref);
end Sloc_To_String;
--------------------
-- Sloc_To_String --
--------------------
function Sloc_To_String (Sptr : Source_Ptr; Ref : Source_Ptr) return String
is
begin
if Sptr = No_Location then
return "at unknown location";
elsif Sptr = System_Location then
return "in package System";
elsif Sptr = Standard_Location then
return "in package Standard";
elsif Sptr = Standard_ASCII_Location then
return "in package Standard.ASCII";
else
if Full_File_Name (Get_Source_File_Index (Sptr))
/= Full_File_Name (Get_Source_File_Index (Ref))
then
return "at " & To_String (Sptr);
else
return "at line " & Line_To_String (Sptr);
end if;
end if;
end Sloc_To_String;
------------------
-- To_Full_Span --
------------------
function To_Full_Span (N : Node_Id) return Source_Span
is
Fst, Lst : Node_Id;
begin
First_And_Last_Nodes (N, Fst, Lst);
return To_Span (Ptr => Sloc (N),
First => First_Sloc (Fst),
Last => Last_Sloc (Lst));
end To_Full_Span;
---------------
-- To_String --
---------------
function To_String (Id : Diagnostic_Id) return String is
begin
if Id = No_Diagnostic_Id then
return "GNAT0000";
else
return Id'Img;
end if;
end To_String;
-------------
-- To_Name --
-------------
function To_Name (E : Entity_Id) return String is
begin
-- The name of the node operator "&" has many special cases. Reuse the
-- node to name conversion implementation from the errout package for
-- now.
Error_Msg_Node_1 := E;
Set_Msg_Text ("&", Sloc (E));
return Msg_Buffer (1 .. Msglen);
end To_Name;
------------------
-- To_Type_Name --
------------------
function To_Type_Name (E : Entity_Id) return String is
begin
Error_Msg_Node_1 := E;
Set_Msg_Text ("}", Sloc (E));
return Msg_Buffer (1 .. Msglen);
end To_Type_Name;
--------------------
-- Kind_To_String --
--------------------
function Kind_To_String
(D : Sub_Diagnostic_Type;
Parent : Diagnostic_Type) return String
is
(case D.Kind is
when Continuation => Kind_To_String (Parent),
when Help => "help",
when Note => "note",
when Suggestion => "suggestion");
--------------------
-- Kind_To_String --
--------------------
function Kind_To_String (D : Diagnostic_Type) return String is
(if D.Warn_Err then "error"
else
(case D.Kind is
when Diagnostics.Error | Non_Serious_Error => "error",
when Warning | Restriction_Warning | Default_Warning |
Tagless_Warning => "warning",
when Style => "style",
when Info => "info"));
------------------------------
-- Get_Primary_Labeled_Span --
------------------------------
function Get_Primary_Labeled_Span (Spans : Labeled_Span_List)
return Labeled_Span_Type
is
use Labeled_Span_Lists;
S : Labeled_Span_Type;
It : Iterator;
begin
if Present (Spans) then
It := Iterate (Spans);
while Has_Next (It) loop
Next (It, S);
if S.Is_Primary then
return S;
end if;
end loop;
end if;
return No_Labeled_Span;
end Get_Primary_Labeled_Span;
--------------------
-- Get_Doc_Switch --
--------------------
function Get_Doc_Switch (Diag : Diagnostic_Type) return String is
begin
if Warning_Doc_Switch
and then Diag.Kind in Default_Warning
| Info
| Restriction_Warning
| Style
| Warning
then
if Diag.Switch = No_Switch_Id then
if Diag.Kind = Restriction_Warning then
return "[restriction warning]";
-- Info messages can have a switch tag but they should not have
-- a default switch tag.
elsif Diag.Kind /= Info then
-- For Default_Warning
return "[enabled by default]";
end if;
else
declare
S : constant Switch_Type := Get_Switch (Diag);
begin
return "[-" & S.Short_Name.all & "]";
end;
end if;
end if;
return "";
end Get_Doc_Switch;
--------------------
-- Appears_Before --
--------------------
function Appears_Before (D1, D2 : Diagnostic_Type) return Boolean is
begin
return Appears_Before (Primary_Location (D1).Span.Ptr,
Primary_Location (D2).Span.Ptr);
end Appears_Before;
--------------------
-- Appears_Before --
--------------------
function Appears_Before (P1, P2 : Source_Ptr) return Boolean is
begin
if Get_Source_File_Index (P1) = Get_Source_File_Index (P2) then
if Get_Logical_Line_Number (P1) = Get_Logical_Line_Number (P2) then
return Get_Column_Number (P1) < Get_Column_Number (P2);
else
return Get_Logical_Line_Number (P1) < Get_Logical_Line_Number (P2);
end if;
else
return Get_Source_File_Index (P1) < Get_Source_File_Index (P2);
end if;
end Appears_Before;
------------------------------
-- Insert_Based_On_Location --
------------------------------
procedure Insert_Based_On_Location
(List : Diagnostic_List;
Diagnostic : Diagnostic_Type)
is
use Diagnostics_Lists;
It : Iterator := Iterate (List);
D : Diagnostic_Type;
begin
-- This is the common scenario where the error is reported at the
-- natural order the tree is processed. This saves a lot of time when
-- looking for the correct position in the list when there are a lot of
-- diagnostics.
if Present (List) and then
not Is_Empty (List) and then
Appears_Before (Last (List), Diagnostic)
then
Append (List, Diagnostic);
else
while Has_Next (It) loop
Next (It, D);
if Appears_Before (Diagnostic, D) then
Insert_Before (List, D, Diagnostic);
return;
end if;
end loop;
Append (List, Diagnostic);
end if;
end Insert_Based_On_Location;
end Diagnostics.Utils;
|