Add assember CFI directives to millicode division and remainder routines.
[official-gcc.git] / gcc / ada / errout.adb
blob96b56ffc57a4a10c9179a100e47eed2414f234f5
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E R R O U T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- Warning: Error messages can be generated during Gigi processing by direct
27 -- calls to error message routines, so it is essential that the processing
28 -- in this body be consistent with the requirements for the Gigi processing
29 -- environment, and that in particular, no disallowed table expansion is
30 -- allowed to occur.
32 with Atree; use Atree;
33 with Casing; use Casing;
34 with Csets; use Csets;
35 with Debug; use Debug;
36 with Einfo; use Einfo;
37 with Einfo.Entities; use Einfo.Entities;
38 with Einfo.Utils; use Einfo.Utils;
39 with Erroutc; use Erroutc;
40 with Gnatvsn; use Gnatvsn;
41 with Lib; use Lib;
42 with Opt; use Opt;
43 with Nlists; use Nlists;
44 with Output; use Output;
45 with Scans; use Scans;
46 with Sem_Aux; use Sem_Aux;
47 with Sinput; use Sinput;
48 with Sinfo; use Sinfo;
49 with Sinfo.Nodes; use Sinfo.Nodes;
50 with Sinfo.Utils; use Sinfo.Utils;
51 with Snames; use Snames;
52 with Stand; use Stand;
53 with Stylesw; use Stylesw;
54 with System.OS_Lib;
55 with Uname; use Uname;
56 with Warnsw;
58 package body Errout is
60 Errors_Must_Be_Ignored : Boolean := False;
61 -- Set to True by procedure Set_Ignore_Errors (True), when calls to error
62 -- message procedures should be ignored (when parsing irrelevant text in
63 -- sources being preprocessed).
65 Finalize_Called : Boolean := False;
66 -- Set True if the Finalize routine has been called
68 Warn_On_Instance : Boolean;
69 -- Flag set true for warning message to be posted on instance
71 ------------------------------------
72 -- Table of Non-Instance Messages --
73 ------------------------------------
75 -- This table contains an entry for every error message processed by the
76 -- Error_Msg routine that is not posted on generic (or inlined) instance.
77 -- As explained in further detail in the Error_Msg procedure body, this
78 -- table is used to avoid posting redundant messages on instances.
80 type NIM_Record is record
81 Msg : String_Ptr;
82 Loc : Source_Ptr;
83 end record;
84 -- Type used to store text and location of one message
86 package Non_Instance_Msgs is new Table.Table (
87 Table_Component_Type => NIM_Record,
88 Table_Index_Type => Int,
89 Table_Low_Bound => 1,
90 Table_Initial => 100,
91 Table_Increment => 100,
92 Table_Name => "Non_Instance_Msgs");
94 -----------------------
95 -- Local Subprograms --
96 -----------------------
98 procedure Error_Msg_Internal
99 (Msg : String;
100 Span : Source_Span;
101 Opan : Source_Span;
102 Msg_Cont : Boolean;
103 Node : Node_Id);
104 -- This is the low-level routine used to post messages after dealing with
105 -- the issue of messages placed on instantiations (which get broken up
106 -- into separate calls in Error_Msg). Span is the location on which the
107 -- flag will be placed in the output. In the case where the flag is on
108 -- the template, this points directly to the template, not to one of the
109 -- instantiation copies of the template. Opan is the original location
110 -- used to flag the error, and this may indeed point to an instantiation
111 -- copy. So typically we can see Opan pointing to the template location
112 -- in an instantiation copy when Span points to the source location of
113 -- the actual instantiation (i.e the line with the new). Msg_Cont is
114 -- set true if this is a continuation message. Node is the relevant
115 -- Node_Id for this message, to be used to compute the enclosing entity if
116 -- Opt.Include_Subprogram_In_Messages is set.
118 function No_Warnings (N : Node_Or_Entity_Id) return Boolean;
119 -- Determines if warnings should be suppressed for the given node
121 function OK_Node (N : Node_Id) return Boolean;
122 -- Determines if a node is an OK node to place an error message on (return
123 -- True) or if the error message should be suppressed (return False). A
124 -- message is suppressed if the node already has an error posted on it,
125 -- or if it refers to an Etype that has an error posted on it, or if
126 -- it references an Entity that has an error posted on it.
128 procedure Output_JSON_Message (Error_Id : Error_Msg_Id);
129 -- Output error message Error_Id and any subsequent continuation message
130 -- using a JSON format similar to the one GCC uses when passed
131 -- -fdiagnostics-format=json.
133 procedure Output_Source_Line
134 (L : Physical_Line_Number;
135 Sfile : Source_File_Index;
136 Errs : Boolean);
137 -- Outputs text of source line L, in file S, together with preceding line
138 -- number, as described above for Output_Line_Number. The Errs parameter
139 -- indicates if there are errors attached to the line, which forces
140 -- listing on, even in the presence of pragma List (Off).
142 procedure Set_Msg_Insertion_Column;
143 -- Handle column number insertion (@ insertion character)
145 procedure Set_Msg_Insertion_Node;
146 -- Handle node (name from node) insertion (& insertion character)
148 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr);
149 -- Handle type reference (right brace insertion character). Flag is the
150 -- location of the flag, which is provided for the internal call to
151 -- Set_Msg_Insertion_Line_Number,
153 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True);
154 -- Handle unit name insertion ($ insertion character). Depending on Boolean
155 -- parameter Suffix, (spec) or (body) is appended after the unit name.
157 procedure Set_Msg_Node (Node : Node_Id);
158 -- Add the sequence of characters for the name associated with the given
159 -- node to the current message. For N_Designator, N_Selected_Component,
160 -- N_Defining_Program_Unit_Name, and N_Expanded_Name, the Prefix is
161 -- included as well.
163 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr);
164 -- Add a sequence of characters to the current message. The characters may
165 -- be one of the special insertion characters (see documentation in spec).
166 -- Flag is the location at which the error is to be posted, which is used
167 -- to determine whether or not the # insertion needs a file name. The
168 -- variables Msg_Buffer are set on return Msglen.
170 procedure Set_Posted (N : Node_Id);
171 -- Sets the Error_Posted flag on the given node, and all its parents that
172 -- are subexpressions and then on the parent non-subexpression construct
173 -- that contains the original expression. If that parent is a named
174 -- association, the flag is further propagated to its parent. This is done
175 -- in order to guard against cascaded errors. Note that this call has an
176 -- effect for a serious error only.
178 procedure Set_Qualification (N : Nat; E : Entity_Id);
179 -- Outputs up to N levels of qualification for the given entity. For
180 -- example, the entity A.B.C.D will output B.C. if N = 2.
182 function Special_Msg_Delete
183 (Msg : String;
184 N : Node_Or_Entity_Id;
185 E : Node_Or_Entity_Id) return Boolean;
186 -- This function is called from Error_Msg_NEL, passing the message Msg,
187 -- node N on which the error is to be posted, and the entity or node E
188 -- to be used for an & insertion in the message if any. The job of this
189 -- procedure is to test for certain cascaded messages that we would like
190 -- to suppress. If the message is to be suppressed then we return True.
191 -- If the message should be generated (the normal case) False is returned.
193 procedure Unwind_Internal_Type (Ent : in out Entity_Id);
194 -- This procedure is given an entity id for an internal type, i.e. a type
195 -- with an internal name. It unwinds the type to try to get to something
196 -- reasonably printable, generating prefixes like "subtype of", "access
197 -- to", etc along the way in the buffer. The value in Ent on return is the
198 -- final name to be printed. Hopefully this is not an internal name, but in
199 -- some internal name cases, it is an internal name, and has to be printed
200 -- anyway (although in this case the message has been killed if possible).
201 -- The global variable Class_Flag is set to True if the resulting entity
202 -- should have 'Class appended to its name (see Add_Class procedure), and
203 -- is otherwise unchanged.
205 function Warn_Insertion return String;
206 -- This is called for warning messages only (so Warning_Msg_Char is set)
207 -- and returns a corresponding string to use at the beginning of generated
208 -- auxiliary messages, such as "in instantiation at ...".
209 -- "?" returns "??"
210 -- " " returns "?"
211 -- other trimmed, prefixed and suffixed with "?".
213 -----------------------
214 -- Change_Error_Text --
215 -----------------------
217 procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String) is
218 Save_Next : Error_Msg_Id;
219 Err_Id : Error_Msg_Id := Error_Id;
221 begin
222 Set_Msg_Text (New_Msg, Errors.Table (Error_Id).Sptr.Ptr);
223 Errors.Table (Error_Id).Text := new String'(Msg_Buffer (1 .. Msglen));
225 -- If in immediate error message mode, output modified error message now
226 -- This is just a bit tricky, because we want to output just a single
227 -- message, and the messages we modified is already linked in. We solve
228 -- this by temporarily resetting its forward pointer to empty.
230 if Debug_Flag_OO then
231 Save_Next := Errors.Table (Error_Id).Next;
232 Errors.Table (Error_Id).Next := No_Error_Msg;
233 Write_Eol;
234 Output_Source_Line
235 (Errors.Table (Error_Id).Line, Errors.Table (Error_Id).Sfile, True);
236 Output_Error_Msgs (Err_Id);
237 Errors.Table (Error_Id).Next := Save_Next;
238 end if;
239 end Change_Error_Text;
241 ------------------------
242 -- Compilation_Errors --
243 ------------------------
245 function Compilation_Errors return Boolean is
246 begin
247 if not Finalize_Called then
248 raise Program_Error;
249 else
250 return Erroutc.Compilation_Errors;
251 end if;
252 end Compilation_Errors;
254 --------------------------------------
255 -- Delete_Warning_And_Continuations --
256 --------------------------------------
258 procedure Delete_Warning_And_Continuations (Msg : Error_Msg_Id) is
259 Id : Error_Msg_Id;
261 begin
262 pragma Assert (not Errors.Table (Msg).Msg_Cont);
264 Id := Msg;
265 loop
266 declare
267 M : Error_Msg_Object renames Errors.Table (Id);
269 begin
270 if not M.Deleted then
271 M.Deleted := True;
272 Warnings_Detected := Warnings_Detected - 1;
274 if M.Info then
275 Warning_Info_Messages := Warning_Info_Messages - 1;
276 end if;
278 if M.Warn_Err then
279 Warnings_Treated_As_Errors := Warnings_Treated_As_Errors - 1;
280 end if;
281 end if;
283 Id := M.Next;
284 exit when Id = No_Error_Msg;
285 exit when not Errors.Table (Id).Msg_Cont;
286 end;
287 end loop;
288 end Delete_Warning_And_Continuations;
290 ---------------
291 -- Error_Msg --
292 ---------------
294 -- Error_Msg posts a flag at the given location, except that if the
295 -- Flag_Location/Flag_Span points within a generic template and corresponds
296 -- to an instantiation of this generic template, then the actual message
297 -- will be posted on the generic instantiation, along with additional
298 -- messages referencing the generic declaration.
300 procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
301 begin
302 Error_Msg (Msg, To_Span (Flag_Location), Current_Node);
303 end Error_Msg;
305 procedure Error_Msg (Msg : String; Flag_Span : Source_Span) is
306 begin
307 Error_Msg (Msg, Flag_Span, Current_Node);
308 end Error_Msg;
310 procedure Error_Msg
311 (Msg : String;
312 Flag_Location : Source_Ptr;
313 Is_Compile_Time_Pragma : Boolean)
315 Save_Is_Compile_Time_Msg : constant Boolean := Is_Compile_Time_Msg;
316 begin
317 Is_Compile_Time_Msg := Is_Compile_Time_Pragma;
318 Error_Msg (Msg, To_Span (Flag_Location), Current_Node);
319 Is_Compile_Time_Msg := Save_Is_Compile_Time_Msg;
320 end Error_Msg;
322 procedure Error_Msg
323 (Msg : String;
324 Flag_Location : Source_Ptr;
325 N : Node_Id)
327 begin
328 Error_Msg (Msg, To_Span (Flag_Location), N);
329 end Error_Msg;
331 procedure Error_Msg
332 (Msg : String;
333 Flag_Span : Source_Span;
334 N : Node_Id)
336 Flag_Location : constant Source_Ptr := Flag_Span.Ptr;
338 Sindex : Source_File_Index;
339 -- Source index for flag location
341 Orig_Loc : Source_Ptr;
342 -- Original location of Flag_Location (i.e. location in original
343 -- template in instantiation case, otherwise unchanged).
345 begin
346 -- Return if all errors are to be ignored
348 if Get_Ignore_Errors then
349 return;
350 end if;
352 -- If we already have messages, and we are trying to place a message at
353 -- No_Location, then just ignore the attempt since we assume that what
354 -- is happening is some cascaded junk. Note that this is safe in the
355 -- sense that proceeding will surely bomb. We will also bomb if the flag
356 -- location is No_Location and we don't have any messages so far, but
357 -- that is a real bug and a legitimate bomb, so we go ahead.
359 if Flag_Location = No_Location
360 and then Total_Errors_Detected > 0
361 then
362 return;
363 end if;
365 -- Start of processing for new message
367 Sindex := Get_Source_File_Index (Flag_Location);
368 Prescan_Message (Msg);
369 Orig_Loc := Original_Location (Flag_Location);
371 -- If the current location is in an instantiation, the issue arises of
372 -- whether to post the message on the template or the instantiation.
374 -- The way we decide is to see if we have posted the same message on
375 -- the template when we compiled the template (the template is always
376 -- compiled before any instantiations). For this purpose, we use a
377 -- separate table of messages. The reason we do this is twofold:
379 -- First, the messages can get changed by various processing
380 -- including the insertion of tokens etc, making it hard to
381 -- do the comparison.
383 -- Second, we will suppress a warning on a template if it is not in
384 -- the current extended source unit. That's reasonable and means we
385 -- don't want the warning on the instantiation here either, but it
386 -- does mean that the main error table would not in any case include
387 -- the message.
389 if Flag_Location = Orig_Loc then
390 Non_Instance_Msgs.Append ((new String'(Msg), Flag_Location));
391 Warn_On_Instance := False;
393 -- Here we have an instance message
395 else
396 -- Delete if debug flag off, and this message duplicates a message
397 -- already posted on the corresponding template
399 if not Debug_Flag_GG then
400 for J in Non_Instance_Msgs.First .. Non_Instance_Msgs.Last loop
401 if Msg = Non_Instance_Msgs.Table (J).Msg.all
402 and then Non_Instance_Msgs.Table (J).Loc = Orig_Loc
403 then
404 return;
405 end if;
406 end loop;
407 end if;
409 -- No duplicate, so error/warning will be posted on instance
411 Warn_On_Instance := Is_Warning_Msg;
412 end if;
414 -- Ignore warning message that is suppressed for this location. Note
415 -- that style checks are not considered warning messages for this
416 -- purpose.
418 if Is_Warning_Msg and then Warnings_Suppressed (Orig_Loc) /= No_String
419 then
420 return;
422 -- For style messages, check too many messages so far
424 elsif Is_Style_Msg
425 and then Maximum_Messages /= 0
426 and then Warnings_Detected >= Maximum_Messages
427 then
428 return;
430 -- Suppress warnings inside a loop that is known to be null or is
431 -- probably null (i.e. when loop executes only if invalid values
432 -- present). In either case warnings in the loop are likely to be junk.
434 elsif Is_Warning_Msg and then Present (N) then
436 declare
437 P : Node_Id;
439 begin
440 P := Parent (N);
441 while Present (P) loop
442 if Nkind (P) = N_Loop_Statement
443 and then Suppress_Loop_Warnings (P)
444 then
445 return;
446 end if;
448 P := Parent (P);
449 end loop;
450 end;
451 end if;
453 -- The idea at this stage is that we have two kinds of messages
455 -- First, we have those messages that are to be placed as requested at
456 -- Flag_Location. This includes messages that have nothing to do with
457 -- generics, and also messages placed on generic templates that reflect
458 -- an error in the template itself. For such messages we simply call
459 -- Error_Msg_Internal to place the message in the requested location.
461 if Instantiation (Sindex) = No_Location then
462 Error_Msg_Internal (Msg, Flag_Span, Flag_Span, False, N);
463 return;
464 end if;
466 -- If we are trying to flag an error in an instantiation, we may have
467 -- a generic contract violation. What we generate in this case is:
469 -- instantiation error at ...
470 -- original error message
472 -- or
474 -- warning: in instantiation at ...
475 -- warning: original warning message
477 -- or
479 -- info: in instantiation at ...
480 -- info: original info message
482 -- All these messages are posted at the location of the top level
483 -- instantiation. If there are nested instantiations, then the
484 -- instantiation error message can be repeated, pointing to each
485 -- of the relevant instantiations.
487 -- Note: the instantiation mechanism is also shared for inlining of
488 -- subprogram bodies when front end inlining is done. In this case the
489 -- messages have the form:
491 -- in inlined body at ...
492 -- original error message
494 -- or
496 -- warning: in inlined body at ...
497 -- warning: original warning message
499 -- or
501 -- info: in inlined body at ...
502 -- info: original info message
504 -- OK, here we have an instantiation error, and we need to generate the
505 -- error on the instantiation, rather than on the template.
507 declare
508 Actual_Error_Loc : Source_Ptr;
509 -- Location of outer level instantiation in instantiation case, or
510 -- just a copy of Flag_Location in the normal case. This is the
511 -- location where all error messages will actually be posted.
513 Save_Error_Msg_Sloc : constant Source_Ptr := Error_Msg_Sloc;
514 -- Save possible location set for caller's message. We need to use
515 -- Error_Msg_Sloc for the location of the instantiation error but we
516 -- have to preserve a possible original value.
518 X : Source_File_Index;
520 Msg_Cont_Status : Boolean;
521 -- Used to label continuation lines in instantiation case with
522 -- proper Msg_Cont status.
524 begin
525 -- Loop to find highest level instantiation, where all error
526 -- messages will be placed.
528 X := Sindex;
529 loop
530 Actual_Error_Loc := Instantiation (X);
531 X := Get_Source_File_Index (Actual_Error_Loc);
532 exit when Instantiation (X) = No_Location;
533 end loop;
535 -- Since we are generating the messages at the instantiation point in
536 -- any case, we do not want the references to the bad lines in the
537 -- instance to be annotated with the location of the instantiation.
539 Suppress_Instance_Location := True;
540 Msg_Cont_Status := False;
542 -- Loop to generate instantiation messages
544 Error_Msg_Sloc := Flag_Location;
545 X := Get_Source_File_Index (Flag_Location);
546 while Instantiation (X) /= No_Location loop
548 -- Suppress instantiation message on continuation lines
550 if Msg (Msg'First) /= '\' then
552 -- Case of inlined body
554 if Inlined_Body (X) then
555 if Is_Info_Msg then
556 Error_Msg_Internal
557 (Msg => "info: in inlined body #",
558 Span => To_Span (Actual_Error_Loc),
559 Opan => Flag_Span,
560 Msg_Cont => Msg_Cont_Status,
561 Node => N);
563 elsif Is_Warning_Msg then
564 Error_Msg_Internal
565 (Msg => Warn_Insertion & "in inlined body #",
566 Span => To_Span (Actual_Error_Loc),
567 Opan => Flag_Span,
568 Msg_Cont => Msg_Cont_Status,
569 Node => N);
571 elsif Is_Style_Msg then
572 Error_Msg_Internal
573 (Msg => "style: in inlined body #",
574 Span => To_Span (Actual_Error_Loc),
575 Opan => Flag_Span,
576 Msg_Cont => Msg_Cont_Status,
577 Node => N);
579 else
580 Error_Msg_Internal
581 (Msg => "error in inlined body #",
582 Span => To_Span (Actual_Error_Loc),
583 Opan => Flag_Span,
584 Msg_Cont => Msg_Cont_Status,
585 Node => N);
586 end if;
588 -- Case of generic instantiation
590 else
591 if Is_Info_Msg then
592 Error_Msg_Internal
593 (Msg => "info: in instantiation #",
594 Span => To_Span (Actual_Error_Loc),
595 Opan => Flag_Span,
596 Msg_Cont => Msg_Cont_Status,
597 Node => N);
599 elsif Is_Warning_Msg then
600 Error_Msg_Internal
601 (Msg => Warn_Insertion & "in instantiation #",
602 Span => To_Span (Actual_Error_Loc),
603 Opan => Flag_Span,
604 Msg_Cont => Msg_Cont_Status,
605 Node => N);
607 elsif Is_Style_Msg then
608 Error_Msg_Internal
609 (Msg => "style: in instantiation #",
610 Span => To_Span (Actual_Error_Loc),
611 Opan => Flag_Span,
612 Msg_Cont => Msg_Cont_Status,
613 Node => N);
615 else
616 Error_Msg_Internal
617 (Msg => "instantiation error #",
618 Span => To_Span (Actual_Error_Loc),
619 Opan => Flag_Span,
620 Msg_Cont => Msg_Cont_Status,
621 Node => N);
622 end if;
623 end if;
624 end if;
626 Error_Msg_Sloc := Instantiation (X);
627 X := Get_Source_File_Index (Error_Msg_Sloc);
628 Msg_Cont_Status := True;
629 end loop;
631 Suppress_Instance_Location := False;
632 Error_Msg_Sloc := Save_Error_Msg_Sloc;
634 -- Here we output the original message on the outer instantiation
636 Error_Msg_Internal
637 (Msg => Msg,
638 Span => To_Span (Actual_Error_Loc),
639 Opan => Flag_Span,
640 Msg_Cont => Msg_Cont_Status,
641 Node => N);
642 end;
643 end Error_Msg;
645 ----------------------------------
646 -- Error_Msg_Ada_2005_Extension --
647 ----------------------------------
649 procedure Error_Msg_Ada_2005_Extension (Extension : String) is
650 Loc : constant Source_Ptr := Token_Ptr;
651 begin
652 if Ada_Version < Ada_2005 then
653 Error_Msg (Extension & " is an Ada 2005 extension", Loc);
655 if No (Ada_Version_Pragma) then
656 Error_Msg ("\unit must be compiled with -gnat05 switch", Loc);
657 else
658 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
659 Error_Msg ("\incompatible with Ada version set#", Loc);
660 end if;
661 end if;
662 end Error_Msg_Ada_2005_Extension;
664 --------------------------------
665 -- Error_Msg_Ada_2012_Feature --
666 --------------------------------
668 procedure Error_Msg_Ada_2012_Feature (Feature : String; Loc : Source_Ptr) is
669 begin
670 if Ada_Version < Ada_2012 then
671 Error_Msg (Feature & " is an Ada 2012 feature", Loc);
673 if No (Ada_Version_Pragma) then
674 Error_Msg ("\unit must be compiled with -gnat2012 switch", Loc);
675 else
676 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
677 Error_Msg ("\incompatible with Ada version set#", Loc);
678 end if;
679 end if;
680 end Error_Msg_Ada_2012_Feature;
682 --------------------------------
683 -- Error_Msg_Ada_2022_Feature --
684 --------------------------------
686 procedure Error_Msg_Ada_2022_Feature (Feature : String; Loc : Source_Ptr) is
687 begin
688 if Ada_Version < Ada_2022 then
689 Error_Msg (Feature & " is an Ada 2022 feature", Loc);
691 if No (Ada_Version_Pragma) then
692 Error_Msg ("\unit must be compiled with -gnat2022 switch", Loc);
693 else
694 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
695 Error_Msg ("\incompatible with Ada version set#", Loc);
696 end if;
697 end if;
698 end Error_Msg_Ada_2022_Feature;
700 ------------------
701 -- Error_Msg_AP --
702 ------------------
704 procedure Error_Msg_AP (Msg : String) is
705 S1 : Source_Ptr;
706 C : Character;
708 begin
709 -- If we had saved the Scan_Ptr value after scanning the previous
710 -- token, then we would have exactly the right place for putting
711 -- the flag immediately at hand. However, that would add at least
712 -- two instructions to a Scan call *just* to service the possibility
713 -- of an Error_Msg_AP call. So instead we reconstruct that value.
715 -- We have two possibilities, start with Prev_Token_Ptr and skip over
716 -- the current token, which is made harder by the possibility that this
717 -- token may be in error, or start with Token_Ptr and work backwards.
718 -- We used to take the second approach, but it's hard because of
719 -- comments, and harder still because things that look like comments
720 -- can appear inside strings. So now we take the first approach.
722 -- Note: in the case where there is no previous token, Prev_Token_Ptr
723 -- is set to Source_First, which is a reasonable position for the
724 -- error flag in this situation.
726 S1 := Prev_Token_Ptr;
727 C := Source (S1);
729 -- If the previous token is a string literal, we need a special approach
730 -- since there may be white space inside the literal and we don't want
731 -- to stop on that white space.
733 -- Note: since this is an error recovery issue anyway, it is not worth
734 -- worrying about special UTF_32 line terminator characters here.
736 if Prev_Token = Tok_String_Literal then
737 loop
738 S1 := S1 + 1;
740 if Source (S1) = C then
741 S1 := S1 + 1;
742 exit when Source (S1) /= C;
743 elsif Source (S1) in Line_Terminator then
744 exit;
745 end if;
746 end loop;
748 -- Character literal also needs special handling
750 elsif Prev_Token = Tok_Char_Literal then
751 S1 := S1 + 3;
753 -- Otherwise we search forward for the end of the current token, marked
754 -- by a line terminator, white space, a comment symbol or if we bump
755 -- into the following token (i.e. the current token).
757 -- Again, it is not worth worrying about UTF_32 special line terminator
758 -- characters in this context, since this is only for error recovery.
760 else
761 while Source (S1) not in Line_Terminator
762 and then Source (S1) /= ' '
763 and then Source (S1) /= ASCII.HT
764 and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-')
765 and then S1 /= Token_Ptr
766 loop
767 S1 := S1 + 1;
768 end loop;
769 end if;
771 -- S1 is now set to the location for the flag
773 Error_Msg (Msg, S1);
774 end Error_Msg_AP;
776 ------------------
777 -- Error_Msg_BC --
778 ------------------
780 procedure Error_Msg_BC (Msg : String) is
781 begin
782 -- If we are at end of file, post the flag after the previous token
784 if Token = Tok_EOF then
785 Error_Msg_AP (Msg);
787 -- If we are at start of file, post the flag at the current token
789 elsif Token_Ptr = Source_First (Current_Source_File) then
790 Error_Msg_SC (Msg);
792 -- If the character before the current token is a space or a horizontal
793 -- tab, then we place the flag on this character (in the case of a tab
794 -- we would really like to place it in the "last" character of the tab
795 -- space, but that it too much trouble to worry about).
797 elsif Source (Token_Ptr - 1) = ' '
798 or else Source (Token_Ptr - 1) = ASCII.HT
799 then
800 Error_Msg (Msg, Token_Ptr - 1);
802 -- If there is no space or tab before the current token, then there is
803 -- no room to place the flag before the token, so we place it on the
804 -- token instead (this happens for example at the start of a line).
806 else
807 Error_Msg (Msg, Token_Ptr);
808 end if;
809 end Error_Msg_BC;
811 -------------------
812 -- Error_Msg_CRT --
813 -------------------
815 procedure Error_Msg_CRT (Feature : String; N : Node_Id) is
816 begin
817 if No_Run_Time_Mode then
818 Error_Msg_N ('|' & Feature & " not allowed in no run time mode", N);
820 else pragma Assert (Configurable_Run_Time_Mode);
821 Error_Msg_N ('|' & Feature & " not supported by configuration>", N);
822 end if;
824 Configurable_Run_Time_Violations := Configurable_Run_Time_Violations + 1;
825 end Error_Msg_CRT;
827 ------------------
828 -- Error_Msg_PT --
829 ------------------
831 procedure Error_Msg_PT (E : Entity_Id; Iface_Prim : Entity_Id) is
832 begin
833 Error_Msg_N
834 ("illegal overriding of subprogram inherited from interface", E);
836 Error_Msg_Sloc := Sloc (Iface_Prim);
838 if Ekind (E) = E_Function then
839 Error_Msg_N
840 ("\first formal of & declared # must be of mode `IN` "
841 & "or access-to-constant", E);
842 else
843 Error_Msg_N
844 ("\first formal of & declared # must be of mode `OUT`, `IN OUT` "
845 & "or access-to-variable", E);
846 end if;
847 end Error_Msg_PT;
849 -----------------
850 -- Error_Msg_F --
851 -----------------
853 procedure Error_Msg_F (Msg : String; N : Node_Id) is
854 Fst, Lst : Node_Id;
855 begin
856 First_And_Last_Nodes (N, Fst, Lst);
857 Error_Msg_NEL (Msg, N, N,
858 To_Span (Ptr => Sloc (Fst),
859 First => First_Sloc (Fst),
860 Last => Last_Sloc (Lst)));
861 end Error_Msg_F;
863 ------------------
864 -- Error_Msg_FE --
865 ------------------
867 procedure Error_Msg_FE
868 (Msg : String;
869 N : Node_Id;
870 E : Node_Or_Entity_Id)
872 Fst, Lst : Node_Id;
873 begin
874 First_And_Last_Nodes (N, Fst, Lst);
875 Error_Msg_NEL (Msg, N, E,
876 To_Span (Ptr => Sloc (Fst),
877 First => First_Sloc (Fst),
878 Last => Last_Sloc (Lst)));
879 end Error_Msg_FE;
881 ------------------------------
882 -- Error_Msg_GNAT_Extension --
883 ------------------------------
885 procedure Error_Msg_GNAT_Extension
886 (Extension : String;
887 Loc : Source_Ptr;
888 Is_Core_Extension : Boolean := False)
890 begin
891 if (if Is_Core_Extension
892 then Core_Extensions_Allowed
893 else All_Extensions_Allowed)
894 then
895 return;
896 end if;
898 Error_Msg (Extension & " is a 'G'N'A'T-specific extension", Loc);
900 if No (Ada_Version_Pragma) then
901 if Is_Core_Extension then
902 Error_Msg
903 ("\unit must be compiled with -gnatX '[or -gnatX0'] " &
904 "or use pragma Extensions_Allowed (On) '[or All']", Loc);
905 else
906 Error_Msg
907 ("\unit must be compiled with -gnatX0 " &
908 "or use pragma Extensions_Allowed (All)", Loc);
909 end if;
910 else
911 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
912 Error_Msg ("\incompatible with Ada version set#", Loc);
913 if Is_Core_Extension then
914 Error_Msg
915 ("\must use pragma Extensions_Allowed (On) '[or All']", Loc);
916 else
917 Error_Msg
918 ("\must use pragma Extensions_Allowed (All)", Loc);
919 end if;
920 end if;
921 end Error_Msg_GNAT_Extension;
923 ------------------------
924 -- Error_Msg_Internal --
925 ------------------------
927 procedure Error_Msg_Internal
928 (Msg : String;
929 Span : Source_Span;
930 Opan : Source_Span;
931 Msg_Cont : Boolean;
932 Node : Node_Id)
934 Sptr : constant Source_Ptr := Span.Ptr;
935 Optr : constant Source_Ptr := Opan.Ptr;
937 Next_Msg : Error_Msg_Id;
938 -- Pointer to next message at insertion point
940 Prev_Msg : Error_Msg_Id;
941 -- Pointer to previous message at insertion point
943 Temp_Msg : Error_Msg_Id;
945 Warn_Err : Boolean;
946 -- Set if warning to be treated as error
948 procedure Handle_Serious_Error;
949 -- Internal procedure to do all error message handling for a serious
950 -- error message, other than bumping the error counts and arranging
951 -- for the message to be output.
953 --------------------------
954 -- Handle_Serious_Error --
955 --------------------------
957 procedure Handle_Serious_Error is
958 begin
959 -- Turn off code generation if not done already
961 if Operating_Mode = Generate_Code then
962 Operating_Mode := Check_Semantics;
963 Expander_Active := False;
964 end if;
966 -- Set the fatal error flag in the unit table unless we are in
967 -- Try_Semantics mode (in which case we set ignored mode if not
968 -- currently set. This stops the semantics from being performed
969 -- if we find a serious error. This is skipped if we are currently
970 -- dealing with the configuration pragma file.
972 if Current_Source_Unit /= No_Unit then
973 declare
974 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
975 begin
976 if Try_Semantics then
977 if Fatal_Error (U) = None then
978 Set_Fatal_Error (U, Error_Ignored);
979 end if;
980 else
981 Set_Fatal_Error (U, Error_Detected);
982 end if;
983 end;
984 end if;
986 -- Disable warnings on unused use clauses and the like. Otherwise, an
987 -- error might hide a reference to an entity in a used package, so
988 -- after fixing the error, the use clause no longer looks like it was
989 -- unused.
991 Warnsw.Check_Unreferenced := False;
992 Warnsw.Check_Unreferenced_Formals := False;
993 end Handle_Serious_Error;
995 -- Start of processing for Error_Msg_Internal
997 begin
998 -- Detect common mistake of prefixing or suffixing the message with a
999 -- space character.
1001 pragma Assert (Msg (Msg'First) /= ' ' and then Msg (Msg'Last) /= ' ');
1003 if Raise_Exception_On_Error /= 0 then
1004 raise Error_Msg_Exception;
1005 end if;
1007 Continuation := Msg_Cont;
1008 Continuation_New_Line := False;
1009 Suppress_Message := False;
1010 Kill_Message := False;
1011 Set_Msg_Text (Msg, Sptr);
1013 -- Kill continuation if parent message killed
1015 if Continuation and Last_Killed then
1016 return;
1017 end if;
1019 -- Return without doing anything if message is suppressed
1021 if Suppress_Message
1022 and then not All_Errors_Mode
1023 and then not Is_Warning_Msg
1024 and then not Is_Unconditional_Msg
1025 then
1026 if not Continuation then
1027 Last_Killed := True;
1028 end if;
1030 return;
1031 end if;
1033 -- Return without doing anything if message is killed and this is not
1034 -- the first error message. The philosophy is that if we get a weird
1035 -- error message and we already have had a message, then we hope the
1036 -- weird message is a junk cascaded message
1038 if Kill_Message
1039 and then not All_Errors_Mode
1040 and then Total_Errors_Detected /= 0
1041 then
1042 if not Continuation then
1043 Last_Killed := True;
1044 end if;
1046 return;
1047 end if;
1049 -- Special check for warning message to see if it should be output
1051 if Is_Warning_Msg then
1053 -- Immediate return if warning message and warnings are suppressed
1055 if Warnings_Suppressed (Optr) /= No_String
1056 or else
1057 Warnings_Suppressed (Sptr) /= No_String
1058 then
1059 Cur_Msg := No_Error_Msg;
1060 return;
1061 end if;
1063 -- If the flag location is in the main extended source unit then for
1064 -- sure we want the warning since it definitely belongs
1066 if In_Extended_Main_Source_Unit (Sptr) then
1067 null;
1069 -- If the main unit has not been read yet. The warning must be on
1070 -- a configuration file: gnat.adc or user-defined. This means we
1071 -- are not parsing the main unit yet, so skip following checks.
1073 elsif No (Cunit (Main_Unit)) then
1074 null;
1076 -- If the flag location is not in the extended main source unit, then
1077 -- we want to eliminate the warning, unless it is in the extended
1078 -- main code unit and we want warnings on the instance.
1080 elsif In_Extended_Main_Code_Unit (Sptr) and then Warn_On_Instance then
1081 null;
1083 -- Keep warning if debug flag G set
1085 elsif Debug_Flag_GG then
1086 null;
1088 -- Keep warning if message text contains !!
1090 elsif Has_Double_Exclam then
1091 null;
1093 -- Here is where we delete a warning from a with'ed unit
1095 else
1096 Cur_Msg := No_Error_Msg;
1098 if not Continuation then
1099 Last_Killed := True;
1100 end if;
1102 return;
1103 end if;
1104 end if;
1106 -- If message is to be ignored in special ignore message mode, this is
1107 -- where we do this special processing, bypassing message output.
1109 if Ignore_Errors_Enable > 0 then
1110 if Is_Serious_Error then
1111 Handle_Serious_Error;
1112 end if;
1114 return;
1115 end if;
1117 -- If error message line length set, and this is a continuation message
1118 -- then all we do is to append the text to the text of the last message
1119 -- with a comma space separator (eliminating a possible (style) or
1120 -- info prefix).
1122 if Error_Msg_Line_Length /= 0 and then Continuation then
1123 Cur_Msg := Errors.Last;
1125 declare
1126 Oldm : String_Ptr := Errors.Table (Cur_Msg).Text;
1127 Newm : String (1 .. Oldm'Last + 2 + Msglen);
1128 Newl : Natural;
1129 M : Natural;
1131 begin
1132 -- First copy old message to new one and free it
1134 Newm (Oldm'Range) := Oldm.all;
1135 Newl := Oldm'Length;
1136 Free (Oldm);
1138 -- Remove (style) or info: at start of message
1140 if Msglen > 8 and then Msg_Buffer (1 .. 8) = "(style) " then
1141 M := 9;
1143 elsif Msglen > 6 and then Msg_Buffer (1 .. 6) = "info: " then
1144 M := 7;
1146 else
1147 M := 1;
1148 end if;
1150 -- Now deal with separation between messages. Normally this is
1151 -- simply comma space, but there are some special cases.
1153 -- If continuation new line, then put actual NL character in msg
1155 if Continuation_New_Line then
1156 Newl := Newl + 1;
1157 Newm (Newl) := ASCII.LF;
1159 -- If continuation message is enclosed in parentheses, then
1160 -- special treatment (don't need a comma, and we want to combine
1161 -- successive parenthetical remarks into a single one with
1162 -- separating commas).
1164 elsif Msg_Buffer (M) = '(' and then Msg_Buffer (Msglen) = ')' then
1166 -- Case where existing message ends in right paren, remove
1167 -- and separate parenthetical remarks with a comma.
1169 if Newm (Newl) = ')' then
1170 Newm (Newl) := ',';
1171 Msg_Buffer (M) := ' ';
1173 -- Case where we are adding new parenthetical comment
1175 else
1176 Newl := Newl + 1;
1177 Newm (Newl) := ' ';
1178 end if;
1180 -- Case where continuation not in parens and no new line
1182 else
1183 Newm (Newl + 1 .. Newl + 2) := ", ";
1184 Newl := Newl + 2;
1185 end if;
1187 -- Append new message
1189 Newm (Newl + 1 .. Newl + Msglen - M + 1) :=
1190 Msg_Buffer (M .. Msglen);
1191 Newl := Newl + Msglen - M + 1;
1192 Errors.Table (Cur_Msg).Text := new String'(Newm (1 .. Newl));
1194 -- Update warning msg flag and message doc char if needed
1196 if Is_Warning_Msg then
1197 if not Errors.Table (Cur_Msg).Warn then
1198 Errors.Table (Cur_Msg).Warn := True;
1199 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1201 elsif Warning_Msg_Char /= " " then
1202 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1203 end if;
1204 end if;
1205 end;
1207 return;
1208 end if;
1210 -- Here we build a new error object
1212 Errors.Append
1213 ((Text => new String'(Msg_Buffer (1 .. Msglen)),
1214 Next => No_Error_Msg,
1215 Prev => No_Error_Msg,
1216 Sptr => Span,
1217 Optr => Opan,
1218 Insertion_Sloc => (if Has_Insertion_Line then Error_Msg_Sloc
1219 else No_Location),
1220 Sfile => Get_Source_File_Index (Sptr),
1221 Line => Get_Physical_Line_Number (Sptr),
1222 Col => Get_Column_Number (Sptr),
1223 Compile_Time_Pragma => Is_Compile_Time_Msg,
1224 Warn => Is_Warning_Msg,
1225 Info => Is_Info_Msg,
1226 Check => Is_Check_Msg,
1227 Warn_Err => False, -- reset below
1228 Warn_Chr => Warning_Msg_Char,
1229 Warn_Runtime_Raise => Is_Runtime_Raise,
1230 Style => Is_Style_Msg,
1231 Serious => Is_Serious_Error,
1232 Uncond => Is_Unconditional_Msg,
1233 Msg_Cont => Continuation,
1234 Deleted => False,
1235 Node => Node));
1236 Cur_Msg := Errors.Last;
1238 -- Test if warning to be treated as error
1240 Warn_Err :=
1241 (Is_Warning_Msg or Is_Style_Msg)
1242 and then (Warning_Treated_As_Error (Msg_Buffer (1 .. Msglen))
1243 or else
1244 Warning_Treated_As_Error (Get_Warning_Tag (Cur_Msg)));
1246 -- Propagate Warn_Err to this message and preceding continuations.
1247 -- Likewise, propagate Is_Warning_Msg and Is_Runtime_Raise, because the
1248 -- current continued message could have been escalated from warning to
1249 -- error.
1251 for J in reverse 1 .. Errors.Last loop
1252 Errors.Table (J).Warn_Err := Warn_Err;
1253 Errors.Table (J).Warn := Is_Warning_Msg;
1254 Errors.Table (J).Warn_Runtime_Raise := Is_Runtime_Raise;
1255 exit when not Errors.Table (J).Msg_Cont;
1256 end loop;
1258 -- If immediate errors mode set, output error message now. Also output
1259 -- now if the -d1 debug flag is set (so node number message comes out
1260 -- just before actual error message)
1262 if Debug_Flag_OO or else Debug_Flag_1 then
1263 Write_Eol;
1264 Output_Source_Line
1265 (Errors.Table (Cur_Msg).Line, Errors.Table (Cur_Msg).Sfile, True);
1266 Temp_Msg := Cur_Msg;
1267 Output_Error_Msgs (Temp_Msg);
1269 -- If not in immediate errors mode, then we insert the message in the
1270 -- error chain for later output by Finalize. The messages are sorted
1271 -- first by unit (main unit comes first), and within a unit by source
1272 -- location (earlier flag location first in the chain).
1274 else
1275 -- First a quick check, does this belong at the very end of the chain
1276 -- of error messages. This saves a lot of time in the normal case if
1277 -- there are lots of messages.
1279 if Last_Error_Msg /= No_Error_Msg
1280 and then Errors.Table (Cur_Msg).Sfile =
1281 Errors.Table (Last_Error_Msg).Sfile
1282 and then (Sptr > Errors.Table (Last_Error_Msg).Sptr.Ptr
1283 or else
1284 (Sptr = Errors.Table (Last_Error_Msg).Sptr.Ptr
1285 and then
1286 Optr > Errors.Table (Last_Error_Msg).Optr.Ptr))
1287 then
1288 Prev_Msg := Last_Error_Msg;
1289 Next_Msg := No_Error_Msg;
1291 -- Otherwise do a full sequential search for the insertion point
1293 else
1294 Prev_Msg := No_Error_Msg;
1295 Next_Msg := First_Error_Msg;
1296 while Next_Msg /= No_Error_Msg loop
1297 exit when
1298 Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
1300 if Errors.Table (Cur_Msg).Sfile = Errors.Table (Next_Msg).Sfile
1301 then
1302 exit when Sptr < Errors.Table (Next_Msg).Sptr.Ptr
1303 or else (Sptr = Errors.Table (Next_Msg).Sptr.Ptr
1304 and then
1305 Optr < Errors.Table (Next_Msg).Optr.Ptr);
1306 end if;
1308 Prev_Msg := Next_Msg;
1309 Next_Msg := Errors.Table (Next_Msg).Next;
1310 end loop;
1311 end if;
1313 -- Now we insert the new message in the error chain.
1315 -- The possible insertion point for the new message is after Prev_Msg
1316 -- and before Next_Msg. However, this is where we do a special check
1317 -- for redundant parsing messages, defined as messages posted on the
1318 -- same line. The idea here is that probably such messages are junk
1319 -- from the parser recovering. In full errors mode, we don't do this
1320 -- deletion, but otherwise such messages are discarded at this stage.
1322 if Prev_Msg /= No_Error_Msg
1323 and then Errors.Table (Prev_Msg).Line =
1324 Errors.Table (Cur_Msg).Line
1325 and then Errors.Table (Prev_Msg).Sfile =
1326 Errors.Table (Cur_Msg).Sfile
1327 and then Compiler_State = Parsing
1328 and then not All_Errors_Mode
1329 then
1330 -- Don't delete unconditional messages and at this stage, don't
1331 -- delete continuation lines; we attempted to delete those earlier
1332 -- if the parent message was deleted.
1334 if not Errors.Table (Cur_Msg).Uncond
1335 and then not Continuation
1336 then
1337 -- Don't delete if prev msg is warning and new msg is an error.
1338 -- This is because we don't want a real error masked by a
1339 -- warning. In all other cases (that is parse errors for the
1340 -- same line that are not unconditional) we do delete the
1341 -- message. This helps to avoid junk extra messages from
1342 -- cascaded parsing errors
1344 if not (Errors.Table (Prev_Msg).Warn
1345 or else
1346 Errors.Table (Prev_Msg).Style)
1347 or else
1348 (Errors.Table (Cur_Msg).Warn
1349 or else
1350 Errors.Table (Cur_Msg).Style)
1351 then
1352 -- All tests passed, delete the message by simply returning
1353 -- without any further processing.
1355 pragma Assert (not Continuation);
1357 Last_Killed := True;
1358 return;
1359 end if;
1360 end if;
1361 end if;
1363 -- Come here if message is to be inserted in the error chain
1365 if not Continuation then
1366 Last_Killed := False;
1367 end if;
1369 if Prev_Msg = No_Error_Msg then
1370 First_Error_Msg := Cur_Msg;
1371 else
1372 Errors.Table (Prev_Msg).Next := Cur_Msg;
1373 end if;
1375 Errors.Table (Cur_Msg).Next := Next_Msg;
1377 if Next_Msg = No_Error_Msg then
1378 Last_Error_Msg := Cur_Msg;
1379 end if;
1380 end if;
1382 -- Bump appropriate statistics counts
1384 if Errors.Table (Cur_Msg).Info then
1386 -- Could be (usually is) both "info" and "warning"
1388 if Errors.Table (Cur_Msg).Warn then
1389 Warning_Info_Messages := Warning_Info_Messages + 1;
1390 Warnings_Detected := Warnings_Detected + 1;
1391 else
1392 Report_Info_Messages := Report_Info_Messages + 1;
1393 end if;
1395 elsif Errors.Table (Cur_Msg).Warn
1396 or else Errors.Table (Cur_Msg).Style
1397 then
1398 Warnings_Detected := Warnings_Detected + 1;
1400 elsif Errors.Table (Cur_Msg).Check then
1401 Check_Messages := Check_Messages + 1;
1403 else
1404 Total_Errors_Detected := Total_Errors_Detected + 1;
1406 if Errors.Table (Cur_Msg).Serious then
1407 Serious_Errors_Detected := Serious_Errors_Detected + 1;
1408 Handle_Serious_Error;
1410 -- If not serious error, set Fatal_Error to indicate ignored error
1412 else
1413 declare
1414 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
1415 begin
1416 if Fatal_Error (U) = None then
1417 Set_Fatal_Error (U, Error_Ignored);
1418 end if;
1419 end;
1420 end if;
1421 end if;
1423 -- Record warning message issued
1425 if Errors.Table (Cur_Msg).Warn
1426 and then not Errors.Table (Cur_Msg).Msg_Cont
1427 then
1428 Warning_Msg := Cur_Msg;
1429 end if;
1431 -- If too many warnings turn off warnings
1433 if Maximum_Messages /= 0 then
1434 if Warnings_Detected = Maximum_Messages then
1435 Warning_Mode := Suppress;
1436 end if;
1438 -- If too many errors abandon compilation
1440 if Total_Errors_Detected = Maximum_Messages then
1441 raise Unrecoverable_Error;
1442 end if;
1443 end if;
1444 end Error_Msg_Internal;
1446 -----------------
1447 -- Error_Msg_N --
1448 -----------------
1450 procedure Error_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
1451 Fst, Lst : Node_Id;
1452 begin
1453 First_And_Last_Nodes (N, Fst, Lst);
1454 Error_Msg_NEL (Msg, N, N,
1455 To_Span (Ptr => Sloc (N),
1456 First => First_Sloc (Fst),
1457 Last => Last_Sloc (Lst)));
1458 end Error_Msg_N;
1460 ------------------
1461 -- Error_Msg_NE --
1462 ------------------
1464 procedure Error_Msg_NE
1465 (Msg : String;
1466 N : Node_Or_Entity_Id;
1467 E : Node_Or_Entity_Id)
1469 Fst, Lst : Node_Id;
1470 begin
1471 First_And_Last_Nodes (N, Fst, Lst);
1472 Error_Msg_NEL (Msg, N, E,
1473 To_Span (Ptr => Sloc (N),
1474 First => First_Sloc (Fst),
1475 Last => Last_Sloc (Lst)));
1476 end Error_Msg_NE;
1478 -------------------
1479 -- Error_Msg_NEL --
1480 -------------------
1482 procedure Error_Msg_NEL
1483 (Msg : String;
1484 N : Node_Or_Entity_Id;
1485 E : Node_Or_Entity_Id;
1486 Flag_Location : Source_Ptr)
1488 Fst, Lst : Node_Id;
1489 begin
1490 First_And_Last_Nodes (N, Fst, Lst);
1491 Error_Msg_NEL
1492 (Msg, N, E,
1493 To_Span (Ptr => Flag_Location,
1494 First => Source_Ptr'Min (Flag_Location, First_Sloc (Fst)),
1495 Last => Source_Ptr'Max (Flag_Location, Last_Sloc (Lst))));
1496 end Error_Msg_NEL;
1498 procedure Error_Msg_NEL
1499 (Msg : String;
1500 N : Node_Or_Entity_Id;
1501 E : Node_Or_Entity_Id;
1502 Flag_Span : Source_Span)
1504 begin
1505 if Special_Msg_Delete (Msg, N, E) then
1506 return;
1507 end if;
1509 Prescan_Message (Msg);
1511 -- Special handling for warning messages
1513 if Is_Warning_Msg then
1515 -- Suppress if no warnings set for either entity or node
1517 if No_Warnings (N) or else No_Warnings (E) then
1519 -- Disable any continuation messages as well
1521 Last_Killed := True;
1522 return;
1523 end if;
1524 end if;
1526 -- Test for message to be output
1528 if All_Errors_Mode
1529 or else Is_Unconditional_Msg
1530 or else Is_Warning_Msg
1531 or else OK_Node (N)
1532 or else (Msg (Msg'First) = '\' and then not Last_Killed)
1533 then
1534 Debug_Output (N);
1535 Error_Msg_Node_1 := E;
1536 Error_Msg (Msg, Flag_Span, N);
1538 else
1539 Last_Killed := True;
1540 end if;
1542 if not Get_Ignore_Errors then
1543 Set_Posted (N);
1544 end if;
1545 end Error_Msg_NEL;
1547 ------------------
1548 -- Error_Msg_NW --
1549 ------------------
1551 procedure Error_Msg_NW
1552 (Eflag : Boolean;
1553 Msg : String;
1554 N : Node_Or_Entity_Id)
1556 Fst, Lst : Node_Id;
1557 begin
1558 if Eflag
1559 and then In_Extended_Main_Source_Unit (N)
1560 and then Comes_From_Source (N)
1561 then
1562 First_And_Last_Nodes (N, Fst, Lst);
1563 Error_Msg_NEL (Msg, N, N,
1564 To_Span (Ptr => Sloc (N),
1565 First => First_Sloc (Fst),
1566 Last => Last_Sloc (Lst)));
1567 end if;
1568 end Error_Msg_NW;
1570 -----------------
1571 -- Error_Msg_S --
1572 -----------------
1574 procedure Error_Msg_S (Msg : String) is
1575 begin
1576 Error_Msg (Msg, Scan_Ptr);
1577 end Error_Msg_S;
1579 ------------------
1580 -- Error_Msg_SC --
1581 ------------------
1583 procedure Error_Msg_SC (Msg : String) is
1584 begin
1585 -- If we are at end of file, post the flag after the previous token
1587 if Token = Tok_EOF then
1588 Error_Msg_AP (Msg);
1590 -- For all other cases the message is posted at the current token
1591 -- pointer position
1593 else
1594 Error_Msg (Msg, Token_Ptr);
1595 end if;
1596 end Error_Msg_SC;
1598 ------------------
1599 -- Error_Msg_SP --
1600 ------------------
1602 procedure Error_Msg_SP (Msg : String) is
1603 begin
1604 -- Note: in the case where there is no previous token, Prev_Token_Ptr
1605 -- is set to Source_First, which is a reasonable position for the
1606 -- error flag in this situation
1608 Error_Msg (Msg, Prev_Token_Ptr);
1609 end Error_Msg_SP;
1611 --------------
1612 -- Finalize --
1613 --------------
1615 procedure Finalize (Last_Call : Boolean) is
1616 Cur : Error_Msg_Id;
1617 Nxt : Error_Msg_Id;
1618 F : Error_Msg_Id;
1620 procedure Delete_Warning (E : Error_Msg_Id);
1621 -- Delete a warning msg if not already deleted and adjust warning count
1623 --------------------
1624 -- Delete_Warning --
1625 --------------------
1627 procedure Delete_Warning (E : Error_Msg_Id) is
1628 begin
1629 if not Errors.Table (E).Deleted then
1630 Errors.Table (E).Deleted := True;
1631 Warnings_Detected := Warnings_Detected - 1;
1633 if Errors.Table (E).Info then
1634 Warning_Info_Messages := Warning_Info_Messages - 1;
1635 end if;
1636 end if;
1637 end Delete_Warning;
1639 -- Start of processing for Finalize
1641 begin
1642 -- Set Prev pointers
1644 Cur := First_Error_Msg;
1645 while Cur /= No_Error_Msg loop
1646 Nxt := Errors.Table (Cur).Next;
1647 exit when Nxt = No_Error_Msg;
1648 Errors.Table (Nxt).Prev := Cur;
1649 Cur := Nxt;
1650 end loop;
1652 -- Eliminate any duplicated error messages from the list. This is
1653 -- done after the fact to avoid problems with Change_Error_Text.
1655 Cur := First_Error_Msg;
1656 while Cur /= No_Error_Msg loop
1657 Nxt := Errors.Table (Cur).Next;
1659 F := Nxt;
1660 while F /= No_Error_Msg
1661 and then Errors.Table (F).Sptr.Ptr = Errors.Table (Cur).Sptr.Ptr
1662 loop
1663 Check_Duplicate_Message (Cur, F);
1664 F := Errors.Table (F).Next;
1665 end loop;
1667 Cur := Nxt;
1668 end loop;
1670 -- Mark any messages suppressed by specific warnings as Deleted
1672 Cur := First_Error_Msg;
1673 while Cur /= No_Error_Msg loop
1674 declare
1675 CE : Error_Msg_Object renames Errors.Table (Cur);
1676 Tag : constant String := Get_Warning_Tag (Cur);
1678 begin
1679 if (CE.Warn and not CE.Deleted)
1680 and then
1681 (Warning_Specifically_Suppressed (CE.Sptr.Ptr, CE.Text, Tag)
1682 /= No_String
1683 or else
1684 Warning_Specifically_Suppressed (CE.Optr.Ptr, CE.Text, Tag)
1685 /= No_String)
1686 then
1687 Delete_Warning (Cur);
1689 -- If this is a continuation, delete previous parts of message
1691 F := Cur;
1692 while Errors.Table (F).Msg_Cont loop
1693 F := Errors.Table (F).Prev;
1694 exit when F = No_Error_Msg;
1695 Delete_Warning (F);
1696 end loop;
1698 -- Delete any following continuations
1700 F := Cur;
1701 loop
1702 F := Errors.Table (F).Next;
1703 exit when F = No_Error_Msg;
1704 exit when not Errors.Table (F).Msg_Cont;
1705 Delete_Warning (F);
1706 end loop;
1707 end if;
1708 end;
1710 Cur := Errors.Table (Cur).Next;
1711 end loop;
1713 Finalize_Called := True;
1715 -- Check consistency of specific warnings (may add warnings). We only
1716 -- do this on the last call, after all possible warnings are posted.
1718 if Last_Call then
1719 Validate_Specific_Warnings (Error_Msg'Access);
1720 end if;
1721 end Finalize;
1723 ----------------
1724 -- First_Node --
1725 ----------------
1727 function First_Node (C : Node_Id) return Node_Id is
1728 Fst, Lst : Node_Id;
1729 begin
1730 First_And_Last_Nodes (C, Fst, Lst);
1731 return Fst;
1732 end First_Node;
1734 --------------------------
1735 -- First_And_Last_Nodes --
1736 --------------------------
1738 procedure First_And_Last_Nodes
1739 (C : Node_Id;
1740 First_Node, Last_Node : out Node_Id)
1742 Orig : constant Node_Id := Original_Node (C);
1743 Loc : constant Source_Ptr := Sloc (Orig);
1744 Sfile : constant Source_File_Index := Get_Source_File_Index (Loc);
1745 Earliest : Node_Id;
1746 Latest : Node_Id;
1747 Eloc : Source_Ptr;
1748 Lloc : Source_Ptr;
1750 function Test_First_And_Last (N : Node_Id) return Traverse_Result;
1751 -- Function applied to every node in the construct
1753 procedure Search_Tree_First_And_Last is new
1754 Traverse_Proc (Test_First_And_Last);
1755 -- Create traversal procedure
1757 -------------------------
1758 -- Test_First_And_Last --
1759 -------------------------
1761 function Test_First_And_Last (N : Node_Id) return Traverse_Result is
1762 Norig : constant Node_Id := Original_Node (N);
1763 Loc : constant Source_Ptr := Sloc (Norig);
1765 begin
1766 -- Check for earlier
1768 if Loc < Eloc
1770 -- Ignore nodes with no useful location information
1772 and then Loc /= Standard_Location
1773 and then Loc /= No_Location
1775 -- Ignore nodes from a different file. This ensures against cases
1776 -- of strange foreign code somehow being present. We don't want
1777 -- wild placement of messages if that happens.
1779 and then Get_Source_File_Index (Loc) = Sfile
1780 then
1781 Earliest := Norig;
1782 Eloc := Loc;
1783 end if;
1785 -- Check for later
1787 if Loc > Lloc
1789 -- Ignore nodes with no useful location information
1791 and then Loc /= Standard_Location
1792 and then Loc /= No_Location
1794 -- Ignore nodes from a different file. This ensures against cases
1795 -- of strange foreign code somehow being present. We don't want
1796 -- wild placement of messages if that happens.
1798 and then Get_Source_File_Index (Loc) = Sfile
1799 then
1800 Latest := Norig;
1801 Lloc := Loc;
1802 end if;
1804 return OK_Orig;
1805 end Test_First_And_Last;
1807 -- Start of processing for First_And_Last_Nodes
1809 begin
1810 if Nkind (Orig) in N_Subexpr
1811 | N_Declaration
1812 | N_Access_To_Subprogram_Definition
1813 | N_Generic_Instantiation
1814 | N_Later_Decl_Item
1815 | N_Use_Package_Clause
1816 | N_Array_Type_Definition
1817 | N_Renaming_Declaration
1818 | N_Generic_Renaming_Declaration
1819 | N_Assignment_Statement
1820 | N_Raise_Statement
1821 | N_Simple_Return_Statement
1822 | N_Exit_Statement
1823 | N_Pragma
1824 | N_Use_Type_Clause
1825 | N_With_Clause
1826 | N_Attribute_Definition_Clause
1827 | N_Subtype_Indication
1828 then
1829 Earliest := Orig;
1830 Eloc := Loc;
1831 Latest := Orig;
1832 Lloc := Loc;
1833 Search_Tree_First_And_Last (Orig);
1834 First_Node := Earliest;
1835 Last_Node := Latest;
1837 else
1838 First_Node := Orig;
1839 Last_Node := Orig;
1840 end if;
1841 end First_And_Last_Nodes;
1843 ----------------
1844 -- First_Sloc --
1845 ----------------
1847 function First_Sloc (N : Node_Id) return Source_Ptr is
1848 SI : constant Source_File_Index := Source_Index (Get_Source_Unit (N));
1849 SF : constant Source_Ptr := Source_First (SI);
1850 SL : constant Source_Ptr := Source_Last (SI);
1851 F : Node_Id;
1852 S : Source_Ptr;
1854 begin
1855 F := First_Node (N);
1856 S := Sloc (F);
1858 if S not in SF .. SL then
1859 return S;
1860 end if;
1862 -- The following circuit is a bit subtle. When we have parenthesized
1863 -- expressions, then the Sloc will not record the location of the paren,
1864 -- but we would like to post the flag on the paren. So what we do is to
1865 -- crawl up the tree from the First_Node, adjusting the Sloc value for
1866 -- any parentheses we know are present. Yes, we know this circuit is not
1867 -- 100% reliable (e.g. because we don't record all possible paren level
1868 -- values), but this is only for an error message so it is good enough.
1870 Node_Loop : loop
1871 Paren_Loop : for J in 1 .. Paren_Count (F) loop
1873 -- We don't look more than 12 characters behind the current
1874 -- location, and in any case not past the front of the source.
1876 Search_Loop : for K in 1 .. 12 loop
1877 exit Search_Loop when S = SF;
1879 if Source_Text (SI) (S - 1) = '(' then
1880 S := S - 1;
1881 exit Search_Loop;
1883 elsif Source_Text (SI) (S - 1) <= ' ' then
1884 S := S - 1;
1886 else
1887 exit Search_Loop;
1888 end if;
1889 end loop Search_Loop;
1890 end loop Paren_Loop;
1892 exit Node_Loop when F = N;
1893 F := Parent (F);
1894 exit Node_Loop when Nkind (F) not in N_Subexpr;
1895 end loop Node_Loop;
1897 return S;
1898 end First_Sloc;
1900 -----------------------
1901 -- Get_Ignore_Errors --
1902 -----------------------
1904 function Get_Ignore_Errors return Boolean is
1905 begin
1906 return Errors_Must_Be_Ignored;
1907 end Get_Ignore_Errors;
1909 ----------------
1910 -- Initialize --
1911 ----------------
1913 procedure Initialize is
1914 begin
1915 Errors.Init;
1916 First_Error_Msg := No_Error_Msg;
1917 Last_Error_Msg := No_Error_Msg;
1918 Serious_Errors_Detected := 0;
1919 Total_Errors_Detected := 0;
1920 Cur_Msg := No_Error_Msg;
1921 List_Pragmas.Init;
1923 -- Reset counts for warnings
1925 Warnings_Treated_As_Errors := 0;
1926 Warnings_Detected := 0;
1927 Warning_Info_Messages := 0;
1928 Warnings_As_Errors_Count := 0;
1930 -- Initialize warnings tables
1932 Warnings.Init;
1933 Specific_Warnings.Init;
1934 end Initialize;
1936 -------------------------------
1937 -- Is_Size_Too_Small_Message --
1938 -------------------------------
1940 function Is_Size_Too_Small_Message (S : String) return Boolean is
1941 Size_For : constant String := "size for";
1942 pragma Assert (Size_Too_Small_Message (1 .. Size_For'Last) = Size_For);
1943 -- Assert that Size_Too_Small_Message starts with Size_For
1944 begin
1945 return S'Length >= Size_For'Length
1946 and then S (S'First .. S'First + Size_For'Length - 1) = Size_For;
1947 -- True if S starts with Size_For
1948 end Is_Size_Too_Small_Message;
1950 ---------------
1951 -- Last_Node --
1952 ---------------
1954 function Last_Node (C : Node_Id) return Node_Id is
1955 Fst, Lst : Node_Id;
1956 begin
1957 First_And_Last_Nodes (C, Fst, Lst);
1958 return Lst;
1959 end Last_Node;
1961 ---------------
1962 -- Last_Sloc --
1963 ---------------
1965 function Last_Sloc (N : Node_Id) return Source_Ptr is
1966 SI : constant Source_File_Index := Source_Index (Get_Source_Unit (N));
1967 SF : constant Source_Ptr := Source_First (SI);
1968 SL : constant Source_Ptr := Source_Last (SI);
1969 F : Node_Id;
1970 S : Source_Ptr;
1972 begin
1973 F := Last_Node (N);
1974 S := Sloc (F);
1976 if S not in SF .. SL then
1977 return S;
1978 end if;
1980 -- Skip past an identifier
1982 while S in SF .. SL - 1
1983 and then Source_Text (SI) (S + 1)
1985 '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' | '.' | '_'
1986 loop
1987 S := S + 1;
1988 end loop;
1990 -- The following circuit attempts at crawling up the tree from the
1991 -- Last_Node, adjusting the Sloc value for any parentheses we know
1992 -- are present, similarly to what is done in First_Sloc.
1994 Node_Loop : loop
1995 Paren_Loop : for J in 1 .. Paren_Count (F) loop
1997 -- We don't look more than 12 characters after the current
1998 -- location
2000 Search_Loop : for K in 1 .. 12 loop
2001 exit Node_Loop when S = SL;
2003 if Source_Text (SI) (S + 1) = ')' then
2004 S := S + 1;
2005 exit Search_Loop;
2007 elsif Source_Text (SI) (S + 1) <= ' ' then
2008 S := S + 1;
2010 else
2011 exit Search_Loop;
2012 end if;
2013 end loop Search_Loop;
2014 end loop Paren_Loop;
2016 exit Node_Loop when F = N;
2017 F := Parent (F);
2018 exit Node_Loop when Nkind (F) not in N_Subexpr;
2019 end loop Node_Loop;
2021 -- Remove any trailing space
2023 while S in SF + 1 .. SL
2024 and then Source_Text (SI) (S) = ' '
2025 loop
2026 S := S - 1;
2027 end loop;
2029 return S;
2030 end Last_Sloc;
2032 -----------------
2033 -- No_Warnings --
2034 -----------------
2036 function No_Warnings (N : Node_Or_Entity_Id) return Boolean is
2037 begin
2038 if Error_Posted (N) then
2039 return True;
2041 elsif Nkind (N) in N_Entity and then Has_Warnings_Off (N) then
2042 return True;
2044 elsif Is_Entity_Name (N)
2045 and then Present (Entity (N))
2046 and then Has_Warnings_Off (Entity (N))
2047 then
2048 return True;
2050 else
2051 return False;
2052 end if;
2053 end No_Warnings;
2055 -------------
2056 -- OK_Node --
2057 -------------
2059 function OK_Node (N : Node_Id) return Boolean is
2060 K : constant Node_Kind := Nkind (N);
2062 begin
2063 if Error_Posted (N) then
2064 return False;
2066 elsif K in N_Has_Etype
2067 and then Present (Etype (N))
2068 and then Error_Posted (Etype (N))
2069 then
2070 return False;
2072 elsif (K in N_Op
2073 or else K = N_Attribute_Reference
2074 or else K = N_Character_Literal
2075 or else K = N_Expanded_Name
2076 or else K = N_Identifier
2077 or else K = N_Operator_Symbol)
2078 and then Present (Entity (N))
2079 and then Error_Posted (Entity (N))
2080 then
2081 return False;
2082 else
2083 return True;
2084 end if;
2085 end OK_Node;
2087 -------------------------
2088 -- Output_JSON_Message --
2089 -------------------------
2091 procedure Output_JSON_Message (Error_Id : Error_Msg_Id) is
2093 function Is_Continuation (E : Error_Msg_Id) return Boolean;
2094 -- Return True if E is a continuation message.
2096 procedure Write_JSON_Escaped_String (Str : String_Ptr);
2097 procedure Write_JSON_Escaped_String (Str : String);
2098 -- Write each character of Str, taking care of preceding each quote and
2099 -- backslash with a backslash. Note that this escaping differs from what
2100 -- GCC does.
2102 -- Indeed, the JSON specification mandates encoding wide characters
2103 -- either as their direct UTF-8 representation or as their escaped
2104 -- UTF-16 surrogate pairs representation. GCC seems to prefer escaping -
2105 -- we choose to use the UTF-8 representation instead.
2107 procedure Write_JSON_Location (Sptr : Source_Ptr);
2108 -- Write Sptr as a JSON location, an object containing a file attribute,
2109 -- a line number and a column number.
2111 procedure Write_JSON_Span (Error : Error_Msg_Object);
2112 -- Write Error as a JSON span, an object containing a "caret" attribute
2113 -- whose value is the JSON location of Error.Sptr.Ptr. If Sptr.First and
2114 -- Sptr.Last are different from Sptr.Ptr, they will be printed as JSON
2115 -- locations under the names "start" and "finish".
2116 -- When Include_Subprogram_In_Messages is true (-gnatdJ) an additional,
2117 -- non-standard, attribute named "subprogram" will be added, allowing
2118 -- precisely identifying the subprogram surrounding the span.
2120 -----------------------
2121 -- Is_Continuation --
2122 -----------------------
2124 function Is_Continuation (E : Error_Msg_Id) return Boolean is
2125 begin
2126 return E <= Last_Error_Msg and then Errors.Table (E).Msg_Cont;
2127 end Is_Continuation;
2129 -------------------------------
2130 -- Write_JSON_Escaped_String --
2131 -------------------------------
2133 procedure Write_JSON_Escaped_String (Str : String) is
2134 begin
2135 for C of Str loop
2136 if C = '"' or else C = '\' then
2137 Write_Char ('\');
2138 end if;
2140 Write_Char (C);
2141 end loop;
2142 end Write_JSON_Escaped_String;
2144 -------------------------------
2145 -- Write_JSON_Escaped_String --
2146 -------------------------------
2148 procedure Write_JSON_Escaped_String (Str : String_Ptr) is
2149 begin
2150 Write_JSON_Escaped_String (Str.all);
2151 end Write_JSON_Escaped_String;
2153 -------------------------
2154 -- Write_JSON_Location --
2155 -------------------------
2157 procedure Write_JSON_Location (Sptr : Source_Ptr) is
2158 Name : constant File_Name_Type :=
2159 Full_Ref_Name (Get_Source_File_Index (Sptr));
2160 begin
2161 Write_Str ("{""file"":""");
2162 if Full_Path_Name_For_Brief_Errors then
2163 Write_JSON_Escaped_String
2164 (System.OS_Lib.Normalize_Pathname (Get_Name_String (Name)));
2165 else
2166 Write_Name (Name);
2167 end if;
2168 Write_Str (""",""line"":");
2169 Write_Int (Pos (Get_Physical_Line_Number (Sptr)));
2170 Write_Str (", ""column"":");
2171 Write_Int (Nat (Get_Column_Number (Sptr)));
2172 Write_Str ("}");
2173 end Write_JSON_Location;
2175 ---------------------
2176 -- Write_JSON_Span --
2177 ---------------------
2179 procedure Write_JSON_Span (Error : Error_Msg_Object) is
2180 Span : constant Source_Span := Error.Sptr;
2181 begin
2182 Write_Str ("{""caret"":");
2183 Write_JSON_Location (Span.Ptr);
2185 if Span.Ptr /= Span.First then
2186 Write_Str (",""start"":");
2187 Write_JSON_Location (Span.First);
2188 end if;
2190 if Span.Ptr /= Span.Last then
2191 Write_Str (",""finish"":");
2192 Write_JSON_Location (Span.Last);
2193 end if;
2195 if Include_Subprogram_In_Messages then
2196 Write_Str (",""subprogram"":""");
2197 Write_JSON_Escaped_String (Subprogram_Name_Ptr (Error.Node));
2198 Write_Str ("""");
2199 end if;
2201 Write_Str ("}");
2202 end Write_JSON_Span;
2204 -- Local Variables
2206 E : Error_Msg_Id := Error_Id;
2208 Print_Continuations : constant Boolean := not Is_Continuation (E);
2209 -- Do not print continuations messages as children of the current
2210 -- message if the current message is a continuation message.
2212 Option : constant String := Get_Warning_Option (E);
2213 -- The option that triggered this message.
2215 -- Start of processing for Output_JSON_Message
2217 begin
2219 -- Print message kind
2221 Write_Str ("{""kind"":");
2223 if Errors.Table (E).Warn and then not Errors.Table (E).Warn_Err then
2224 Write_Str ("""warning""");
2225 elsif Errors.Table (E).Info or else Errors.Table (E).Check then
2226 Write_Str ("""note""");
2227 else
2228 Write_Str ("""error""");
2229 end if;
2231 -- Print message location
2233 Write_Str (",""locations"":[");
2234 Write_JSON_Span (Errors.Table (E));
2236 if Errors.Table (E).Optr.Ptr /= Errors.Table (E).Sptr.Ptr then
2237 Write_Str (",{""caret"":");
2238 Write_JSON_Location (Errors.Table (E).Optr.Ptr);
2239 Write_Str ("}");
2240 end if;
2242 Write_Str ("]");
2244 -- Print message option, if there is one
2245 if Option /= "" then
2246 Write_Str (",""option"":""" & Option & """");
2247 end if;
2249 -- Print message content
2251 Write_Str (",""message"":""");
2252 Write_JSON_Escaped_String (Errors.Table (E).Text);
2253 Write_Str ("""");
2255 E := E + 1;
2257 if Print_Continuations and then Is_Continuation (E) then
2259 Write_Str (",""children"": [");
2260 Output_JSON_Message (E);
2261 E := E + 1;
2263 while Is_Continuation (E) loop
2264 Write_Str (", ");
2265 Output_JSON_Message (E);
2266 E := E + 1;
2267 end loop;
2269 Write_Str ("]");
2271 end if;
2273 Write_Str ("}");
2274 end Output_JSON_Message;
2276 ---------------------
2277 -- Output_Messages --
2278 ---------------------
2280 procedure Output_Messages is
2282 -- Local subprograms
2284 procedure Write_Error_Summary;
2285 -- Write error summary
2287 procedure Write_Header (Sfile : Source_File_Index);
2288 -- Write header line (compiling or checking given file)
2290 procedure Write_Max_Errors;
2291 -- Write message if max errors reached
2293 procedure Write_Source_Code_Lines
2294 (Span : Source_Span;
2295 SGR_Span : String);
2296 -- Write the source code line corresponding to Span, as follows when
2297 -- Span in on one line:
2299 -- line | actual code line here with Span somewhere
2300 -- | ~~~~~^~~~
2302 -- where the caret on the line points to location Span.Ptr, and the
2303 -- range Span.First..Span.Last is underlined.
2305 -- or when the span is over multiple lines:
2307 -- line | beginning of the Span on this line
2308 -- ... | ...
2309 -- line>| actual code line here with Span.Ptr somewhere
2310 -- ... | ...
2311 -- line | end of the Span on this line
2313 -- or when the span is a simple location, as follows:
2315 -- line | actual code line here with Span somewhere
2316 -- | ^ here
2318 -- where the caret on the line points to location Span.Ptr
2320 -- SGR_Span is the SGR string to start the section of code in the span,
2321 -- that should be closed with SGR_Reset.
2323 -------------------------
2324 -- Write_Error_Summary --
2325 -------------------------
2327 procedure Write_Error_Summary is
2328 begin
2329 -- Extra blank line if error messages or source listing were output
2331 if Total_Errors_Detected + Warnings_Detected > 0 or else Full_List
2332 then
2333 Write_Eol;
2334 end if;
2336 -- Message giving number of lines read and number of errors detected.
2337 -- This normally goes to Standard_Output. The exception is when brief
2338 -- mode is not set, verbose mode (or full list mode) is set, and
2339 -- there are errors. In this case we send the message to standard
2340 -- error to make sure that *something* appears on standard error
2341 -- in an error situation.
2343 if Total_Errors_Detected + Warnings_Detected /= 0
2344 and then not Brief_Output
2345 and then (Verbose_Mode or Full_List)
2346 then
2347 Set_Standard_Error;
2348 end if;
2350 -- Message giving total number of lines. Don't give this message if
2351 -- the Main_Source line is unknown (this happens in error situations,
2352 -- e.g. when integrated preprocessing fails).
2354 if Main_Source_File > No_Source_File then
2355 Write_Str (" ");
2356 Write_Int (Num_Source_Lines (Main_Source_File));
2358 if Num_Source_Lines (Main_Source_File) = 1 then
2359 Write_Str (" line: ");
2360 else
2361 Write_Str (" lines: ");
2362 end if;
2363 end if;
2365 if Total_Errors_Detected = 0 then
2366 Write_Str ("No errors");
2368 elsif Total_Errors_Detected = 1 then
2369 Write_Str ("1 error");
2371 else
2372 Write_Int (Total_Errors_Detected);
2373 Write_Str (" errors");
2374 end if;
2376 -- We now need to output warnings. When using -gnatwe, all warnings
2377 -- should be treated as errors, except for warnings originating from
2378 -- the use of the Compile_Time_Warning pragma. Another situation
2379 -- where a warning might be treated as an error is when the source
2380 -- code contains a Warning_As_Error pragma.
2381 -- When warnings are treated as errors, we still log them as
2382 -- warnings, but we add a message denoting how many of these warnings
2383 -- are also errors.
2385 declare
2386 Warnings_Count : constant Int :=
2387 Warnings_Detected - Warning_Info_Messages;
2389 Compile_Time_Warnings : Int;
2390 -- Number of warnings that come from a Compile_Time_Warning
2391 -- pragma.
2393 Non_Compile_Time_Warnings : Int;
2394 -- Number of warnings that do not come from a Compile_Time_Warning
2395 -- pragmas.
2397 begin
2398 if Warnings_Count > 0 then
2399 Write_Str (", ");
2400 Write_Int (Warnings_Count);
2401 Write_Str (" warning");
2403 if Warnings_Count > 1 then
2404 Write_Char ('s');
2405 end if;
2407 Compile_Time_Warnings := Count_Compile_Time_Pragma_Warnings;
2408 Non_Compile_Time_Warnings :=
2409 Warnings_Count - Compile_Time_Warnings;
2411 if Warning_Mode = Treat_As_Error
2412 and then Non_Compile_Time_Warnings > 0
2413 then
2414 Write_Str (" (");
2416 if Compile_Time_Warnings > 0 then
2417 Write_Int (Non_Compile_Time_Warnings);
2418 Write_Str (" ");
2419 end if;
2421 Write_Str ("treated as error");
2423 if Non_Compile_Time_Warnings > 1 then
2424 Write_Char ('s');
2425 end if;
2427 Write_Char (')');
2429 elsif Warnings_Treated_As_Errors > 0 then
2430 Write_Str (" (");
2432 if Warnings_Treated_As_Errors /= Warnings_Count then
2433 Write_Int (Warnings_Treated_As_Errors);
2434 Write_Str (" ");
2435 end if;
2437 Write_Str ("treated as error");
2439 if Warnings_Treated_As_Errors > 1 then
2440 Write_Str ("s");
2441 end if;
2443 Write_Str (")");
2444 end if;
2445 end if;
2446 end;
2448 if Warning_Info_Messages + Report_Info_Messages /= 0 then
2449 Write_Str (", ");
2450 Write_Int (Warning_Info_Messages + Report_Info_Messages);
2451 Write_Str (" info message");
2453 if Warning_Info_Messages + Report_Info_Messages > 1 then
2454 Write_Char ('s');
2455 end if;
2456 end if;
2458 Write_Eol;
2459 Set_Standard_Output;
2460 end Write_Error_Summary;
2462 ------------------
2463 -- Write_Header --
2464 ------------------
2466 procedure Write_Header (Sfile : Source_File_Index) is
2467 begin
2468 if Verbose_Mode or Full_List then
2469 if Original_Operating_Mode = Generate_Code then
2470 Write_Str ("Compiling: ");
2471 else
2472 Write_Str ("Checking: ");
2473 end if;
2475 Write_Name (Full_File_Name (Sfile));
2477 if not Debug_Flag_7 then
2478 Write_Eol;
2479 Write_Str ("Source file time stamp: ");
2480 Write_Time_Stamp (Sfile);
2481 Write_Eol;
2482 Write_Str ("Compiled at: " & Compilation_Time);
2483 end if;
2485 Write_Eol;
2486 end if;
2487 end Write_Header;
2489 ----------------------
2490 -- Write_Max_Errors --
2491 ----------------------
2493 procedure Write_Max_Errors is
2494 begin
2495 if Maximum_Messages /= 0 then
2496 if Warnings_Detected >= Maximum_Messages then
2497 Set_Standard_Error;
2498 Write_Line ("maximum number of warnings output");
2499 Write_Line ("any further warnings suppressed");
2500 Set_Standard_Output;
2501 end if;
2503 -- If too many errors print message
2505 if Total_Errors_Detected >= Maximum_Messages then
2506 Set_Standard_Error;
2507 Write_Line ("fatal error: maximum number of errors detected");
2508 Set_Standard_Output;
2509 end if;
2510 end if;
2511 end Write_Max_Errors;
2513 -----------------------------
2514 -- Write_Source_Code_Lines --
2515 -----------------------------
2517 procedure Write_Source_Code_Lines
2518 (Span : Source_Span;
2519 SGR_Span : String)
2521 function Get_Line_End
2522 (Buf : Source_Buffer_Ptr;
2523 Loc : Source_Ptr) return Source_Ptr;
2524 -- Get the source location for the end of the line in Buf for Loc. If
2525 -- Loc is past the end of Buf already, return Buf'Last.
2527 function Get_Line_Start
2528 (Buf : Source_Buffer_Ptr;
2529 Loc : Source_Ptr) return Source_Ptr;
2530 -- Get the source location for the start of the line in Buf for Loc
2532 function Image (X : Positive; Width : Positive) return String;
2533 -- Output number X over Width characters, with whitespace padding.
2534 -- Only output the low-order Width digits of X, if X is larger than
2535 -- Width digits.
2537 procedure Write_Buffer
2538 (Buf : Source_Buffer_Ptr;
2539 First : Source_Ptr;
2540 Last : Source_Ptr);
2541 -- Output the characters from First to Last position in Buf, using
2542 -- Write_Buffer_Char.
2544 procedure Write_Buffer_Char
2545 (Buf : Source_Buffer_Ptr;
2546 Loc : Source_Ptr);
2547 -- Output the characters at position Loc in Buf, translating ASCII.HT
2548 -- in a suitable number of spaces so that the output is not modified
2549 -- by starting in a different column that 1.
2551 procedure Write_Line_Marker
2552 (Num : Pos;
2553 Mark : Boolean;
2554 Width : Positive);
2555 -- Output the line number Num over Width characters, with possibly
2556 -- a Mark to denote the line with the main location when reporting
2557 -- a span over multiple lines.
2559 ------------------
2560 -- Get_Line_End --
2561 ------------------
2563 function Get_Line_End
2564 (Buf : Source_Buffer_Ptr;
2565 Loc : Source_Ptr) return Source_Ptr
2567 Cur_Loc : Source_Ptr := Source_Ptr'Min (Loc, Buf'Last);
2568 begin
2569 while Cur_Loc < Buf'Last
2570 and then Buf (Cur_Loc) /= ASCII.LF
2571 loop
2572 Cur_Loc := Cur_Loc + 1;
2573 end loop;
2575 return Cur_Loc;
2576 end Get_Line_End;
2578 --------------------
2579 -- Get_Line_Start --
2580 --------------------
2582 function Get_Line_Start
2583 (Buf : Source_Buffer_Ptr;
2584 Loc : Source_Ptr) return Source_Ptr
2586 Cur_Loc : Source_Ptr := Loc;
2587 begin
2588 while Cur_Loc > Buf'First
2589 and then Buf (Cur_Loc - 1) /= ASCII.LF
2590 loop
2591 Cur_Loc := Cur_Loc - 1;
2592 end loop;
2594 return Cur_Loc;
2595 end Get_Line_Start;
2597 -----------
2598 -- Image --
2599 -----------
2601 function Image (X : Positive; Width : Positive) return String is
2602 Str : String (1 .. Width);
2603 Curr : Natural := X;
2604 begin
2605 for J in reverse 1 .. Width loop
2606 if Curr > 0 then
2607 Str (J) := Character'Val (Character'Pos ('0') + Curr mod 10);
2608 Curr := Curr / 10;
2609 else
2610 Str (J) := ' ';
2611 end if;
2612 end loop;
2614 return Str;
2615 end Image;
2617 ------------------
2618 -- Write_Buffer --
2619 ------------------
2621 procedure Write_Buffer
2622 (Buf : Source_Buffer_Ptr;
2623 First : Source_Ptr;
2624 Last : Source_Ptr)
2626 begin
2627 for Loc in First .. Last loop
2628 Write_Buffer_Char (Buf, Loc);
2629 end loop;
2630 end Write_Buffer;
2632 -----------------------
2633 -- Write_Buffer_Char --
2634 -----------------------
2636 procedure Write_Buffer_Char
2637 (Buf : Source_Buffer_Ptr;
2638 Loc : Source_Ptr)
2640 begin
2641 -- If the character ASCII.HT is not the last one in the file,
2642 -- output as many spaces as the character represents in the
2643 -- original source file.
2645 if Buf (Loc) = ASCII.HT
2646 and then Loc < Buf'Last
2647 then
2648 for X in Get_Column_Number (Loc) ..
2649 Get_Column_Number (Loc + 1) - 1
2650 loop
2651 Write_Char (' ');
2652 end loop;
2654 -- Otherwise output the character itself
2656 else
2657 Write_Char (Buf (Loc));
2658 end if;
2659 end Write_Buffer_Char;
2661 -----------------------
2662 -- Write_Line_Marker --
2663 -----------------------
2665 procedure Write_Line_Marker
2666 (Num : Pos;
2667 Mark : Boolean;
2668 Width : Positive)
2670 begin
2671 Write_Str (Image (Positive (Num), Width => Width));
2672 Write_Str ((if Mark then ">" else " ") & "|");
2673 end Write_Line_Marker;
2675 -- Local variables
2677 Loc : constant Source_Ptr := Span.Ptr;
2678 Line : constant Pos := Pos (Get_Physical_Line_Number (Loc));
2680 Col : constant Natural := Natural (Get_Column_Number (Loc));
2682 Fst : constant Source_Ptr := Span.First;
2683 Line_Fst : constant Pos :=
2684 Pos (Get_Physical_Line_Number (Fst));
2685 Col_Fst : constant Natural :=
2686 Natural (Get_Column_Number (Fst));
2687 Lst : constant Source_Ptr := Span.Last;
2688 Line_Lst : constant Pos :=
2689 Pos (Get_Physical_Line_Number (Lst));
2690 Col_Lst : constant Natural :=
2691 Natural (Get_Column_Number (Lst));
2693 Width : constant := 5;
2694 Buf : Source_Buffer_Ptr;
2695 Cur_Loc : Source_Ptr := Fst;
2696 Cur_Line : Pos := Line_Fst;
2698 -- Start of processing for Write_Source_Code_Lines
2700 begin
2701 if Loc >= First_Source_Ptr then
2702 Buf := Source_Text (Get_Source_File_Index (Loc));
2704 -- First line of the span with actual source code. We retrieve
2705 -- the beginning of the line instead of relying on Col_Fst, as
2706 -- ASCII.HT characters change column numbers by possibly more
2707 -- than one.
2709 Write_Line_Marker
2710 (Cur_Line,
2711 Line_Fst /= Line_Lst and then Cur_Line = Line,
2712 Width);
2713 Write_Buffer (Buf, Get_Line_Start (Buf, Cur_Loc), Cur_Loc - 1);
2715 -- Output the first/caret/last lines of the span, as well as
2716 -- lines that are directly above/below the caret if they complete
2717 -- the gap with first/last lines, otherwise use ... to denote
2718 -- intermediate lines.
2720 -- If the span is on one line and not a simple source location,
2721 -- color it appropriately.
2723 if Line_Fst = Line_Lst
2724 and then Col_Fst /= Col_Lst
2725 then
2726 Write_Str (SGR_Span);
2727 end if;
2729 declare
2730 function Do_Write_Line (Cur_Line : Pos) return Boolean is
2731 (Cur_Line in Line_Fst | Line | Line_Lst
2732 or else
2733 (Cur_Line = Line_Fst + 1 and then Cur_Line = Line - 1)
2734 or else
2735 (Cur_Line = Line + 1 and then Cur_Line = Line_Lst - 1));
2736 begin
2737 while Cur_Loc <= Buf'Last
2738 and then Cur_Loc <= Lst
2739 loop
2740 if Do_Write_Line (Cur_Line) then
2741 Write_Buffer_Char (Buf, Cur_Loc);
2742 end if;
2744 if Buf (Cur_Loc) = ASCII.LF then
2745 Cur_Line := Cur_Line + 1;
2747 -- Output ... for skipped lines
2749 if (Cur_Line = Line
2750 and then not Do_Write_Line (Cur_Line - 1))
2751 or else
2752 (Cur_Line = Line + 1
2753 and then not Do_Write_Line (Cur_Line))
2754 then
2755 Write_Str ((1 .. Width - 3 => ' ') & "... | ...");
2756 Write_Eol;
2757 end if;
2759 -- Display the line marker if the line should be
2760 -- displayed.
2762 if Do_Write_Line (Cur_Line) then
2763 Write_Line_Marker
2764 (Cur_Line,
2765 Line_Fst /= Line_Lst and then Cur_Line = Line,
2766 Width);
2767 end if;
2768 end if;
2770 Cur_Loc := Cur_Loc + 1;
2771 end loop;
2772 end;
2774 if Line_Fst = Line_Lst
2775 and then Col_Fst /= Col_Lst
2776 then
2777 Write_Str (SGR_Reset);
2778 end if;
2780 -- Output the rest of the last line of the span
2782 Write_Buffer (Buf, Cur_Loc, Get_Line_End (Buf, Cur_Loc));
2784 -- If the span is on one line, output a second line with caret
2785 -- sign pointing to location Loc
2787 if Line_Fst = Line_Lst then
2788 Write_Str (String'(1 .. Width => ' '));
2789 Write_Str (" |");
2790 Write_Str (String'(1 .. Col_Fst - 1 => ' '));
2792 Write_Str (SGR_Span);
2794 Write_Str (String'(Col_Fst .. Col - 1 => '~'));
2795 Write_Str ("^");
2796 Write_Str (String'(Col + 1 .. Col_Lst => '~'));
2798 -- If the span is really just a location, add the word "here"
2799 -- to clarify this is the location for the message.
2801 if Col_Fst = Col_Lst then
2802 Write_Str (" here");
2803 end if;
2805 Write_Str (SGR_Reset);
2807 Write_Eol;
2808 end if;
2809 end if;
2810 end Write_Source_Code_Lines;
2812 -- Local variables
2814 E : Error_Msg_Id;
2815 Err_Flag : Boolean;
2816 Use_Prefix : Boolean;
2818 -- Start of processing for Output_Messages
2820 begin
2821 -- Error if Finalize has not been called
2823 if not Finalize_Called then
2824 raise Program_Error;
2825 end if;
2827 -- Reset current error source file if the main unit has a pragma
2828 -- Source_Reference. This ensures outputting the proper name of
2829 -- the source file in this situation.
2831 if Main_Source_File <= No_Source_File
2832 or else Num_SRef_Pragmas (Main_Source_File) /= 0
2833 then
2834 Current_Error_Source_File := No_Source_File;
2835 end if;
2837 if Opt.JSON_Output then
2838 Set_Standard_Error;
2840 E := First_Error_Msg;
2842 -- Find first printable message
2844 while E /= No_Error_Msg and then Errors.Table (E).Deleted loop
2845 E := Errors.Table (E).Next;
2846 end loop;
2848 Write_Char ('[');
2850 if E /= No_Error_Msg then
2852 Output_JSON_Message (E);
2854 E := Errors.Table (E).Next;
2856 -- Skip deleted messages.
2857 -- Also skip continuation messages, as they have already been
2858 -- printed along the message they're attached to.
2860 while E /= No_Error_Msg
2861 and then not Errors.Table (E).Deleted
2862 and then not Errors.Table (E).Msg_Cont
2863 loop
2864 Write_Char (',');
2865 Output_JSON_Message (E);
2866 E := Errors.Table (E).Next;
2867 end loop;
2868 end if;
2870 Write_Char (']');
2872 Set_Standard_Output;
2874 -- Brief Error mode
2876 elsif Brief_Output or (not Full_List and not Verbose_Mode) then
2877 Set_Standard_Error;
2879 E := First_Error_Msg;
2880 while E /= No_Error_Msg loop
2882 -- If -gnatdF is used, separate main messages from previous
2883 -- messages with a newline (unless it is an info message) and
2884 -- make continuation messages follow the main message with only
2885 -- an indentation of two space characters, without repeating
2886 -- file:line:col: prefix.
2888 Use_Prefix :=
2889 not (Debug_Flag_FF and then Errors.Table (E).Msg_Cont);
2891 if not Errors.Table (E).Deleted and then not Debug_Flag_KK then
2893 if Debug_Flag_FF then
2894 if Errors.Table (E).Msg_Cont then
2895 Write_Str (" ");
2896 elsif not Errors.Table (E).Info then
2897 Write_Eol;
2898 end if;
2899 end if;
2901 if Use_Prefix then
2902 Write_Str (SGR_Locus);
2904 if Full_Path_Name_For_Brief_Errors then
2905 Write_Name (Full_Ref_Name (Errors.Table (E).Sfile));
2906 else
2907 Write_Name (Reference_Name (Errors.Table (E).Sfile));
2908 end if;
2910 Write_Char (':');
2911 Write_Int (Int (Physical_To_Logical
2912 (Errors.Table (E).Line,
2913 Errors.Table (E).Sfile)));
2914 Write_Char (':');
2916 if Errors.Table (E).Col < 10 then
2917 Write_Char ('0');
2918 end if;
2920 Write_Int (Int (Errors.Table (E).Col));
2921 Write_Str (": ");
2923 Write_Str (SGR_Reset);
2924 end if;
2926 Output_Msg_Text (E);
2927 Write_Eol;
2929 -- If -gnatdF is used, write the source code line corresponding
2930 -- to the location of the main message (unless it is an info
2931 -- message). Also write the source code line corresponding to
2932 -- an insertion location inside continuation messages.
2934 if Debug_Flag_FF
2935 and then not Errors.Table (E).Info
2936 then
2937 if Errors.Table (E).Msg_Cont then
2938 declare
2939 Loc : constant Source_Ptr :=
2940 Errors.Table (E).Insertion_Sloc;
2941 begin
2942 if Loc /= No_Location then
2943 Write_Source_Code_Lines
2944 (To_Span (Loc), SGR_Span => SGR_Note);
2945 end if;
2946 end;
2948 else
2949 declare
2950 SGR_Span : constant String :=
2951 (if Errors.Table (E).Info then SGR_Note
2952 elsif Errors.Table (E).Warn
2953 and then not Errors.Table (E).Warn_Err
2954 then SGR_Warning
2955 else SGR_Error);
2956 begin
2957 Write_Source_Code_Lines
2958 (Errors.Table (E).Optr, SGR_Span);
2959 end;
2960 end if;
2961 end if;
2962 end if;
2964 E := Errors.Table (E).Next;
2965 end loop;
2967 Set_Standard_Output;
2968 end if;
2970 -- Full source listing case
2972 if Full_List then
2973 List_Pragmas_Index := 1;
2974 List_Pragmas_Mode := True;
2975 E := First_Error_Msg;
2977 -- Normal case, to stdout (copyright notice already output)
2979 if Full_List_File_Name = null then
2980 if not Debug_Flag_7 then
2981 Write_Eol;
2982 end if;
2984 -- Output to file
2986 else
2987 Create_List_File_Access.all (Full_List_File_Name.all);
2988 Set_Special_Output (Write_List_Info_Access.all'Access);
2990 -- Write copyright notice to file
2992 if not Debug_Flag_7 then
2993 Write_Str ("GNAT ");
2994 Write_Str (Gnat_Version_String);
2995 Write_Eol;
2996 Write_Str ("Copyright 1992-" &
2997 Current_Year &
2998 ", Free Software Foundation, Inc.");
2999 Write_Eol;
3000 end if;
3001 end if;
3003 -- First list extended main source file units with errors
3005 for U in Main_Unit .. Last_Unit loop
3006 if In_Extended_Main_Source_Unit (Cunit_Entity (U))
3008 -- If debug flag d.m is set, only the main source is listed
3010 and then (U = Main_Unit or else not Debug_Flag_Dot_M)
3012 -- If the unit of the entity does not come from source, it is
3013 -- an implicit subprogram declaration for a child subprogram.
3014 -- Do not emit errors for it, they are listed with the body.
3016 and then
3017 (No (Cunit_Entity (U))
3018 or else Comes_From_Source (Cunit_Entity (U))
3019 or else not Is_Subprogram (Cunit_Entity (U)))
3021 -- If the compilation unit associated with this unit does not
3022 -- come from source, it means it is an instantiation that should
3023 -- not be included in the source listing.
3025 and then Comes_From_Source (Cunit (U))
3026 then
3027 declare
3028 Sfile : constant Source_File_Index := Source_Index (U);
3030 begin
3031 Write_Eol;
3033 -- Only write the header if Sfile is known
3035 if Sfile > No_Source_File then
3036 Write_Header (Sfile);
3037 Write_Eol;
3038 end if;
3040 -- Normally, we don't want an "error messages from file"
3041 -- message when listing the entire file, so we set the
3042 -- current source file as the current error source file.
3043 -- However, the old style of doing things was to list this
3044 -- message if pragma Source_Reference is present, even for
3045 -- the main unit. Since the purpose of the -gnatd.m switch
3046 -- is to duplicate the old behavior, we skip the reset if
3047 -- this debug flag is set.
3049 if not Debug_Flag_Dot_M then
3050 Current_Error_Source_File := Sfile;
3051 end if;
3053 -- Only output the listing if Sfile is known, to avoid
3054 -- crashing the compiler.
3056 if Sfile > No_Source_File then
3057 for N in 1 .. Last_Source_Line (Sfile) loop
3058 while E /= No_Error_Msg
3059 and then Errors.Table (E).Deleted
3060 loop
3061 E := Errors.Table (E).Next;
3062 end loop;
3064 Err_Flag :=
3065 E /= No_Error_Msg
3066 and then Errors.Table (E).Line = N
3067 and then Errors.Table (E).Sfile = Sfile;
3069 Output_Source_Line (N, Sfile, Err_Flag);
3071 if Err_Flag then
3072 Output_Error_Msgs (E);
3074 if not Debug_Flag_2 then
3075 Write_Eol;
3076 end if;
3077 end if;
3078 end loop;
3079 end if;
3080 end;
3081 end if;
3082 end loop;
3084 -- Then output errors, if any, for subsidiary units not in the
3085 -- main extended unit.
3087 -- Note: if debug flag d.m set, include errors for any units other
3088 -- than the main unit in the extended source unit (e.g. spec and
3089 -- subunits for a body).
3091 while E /= No_Error_Msg
3092 and then (not In_Extended_Main_Source_Unit
3093 (Errors.Table (E).Sptr.Ptr)
3094 or else
3095 (Debug_Flag_Dot_M
3096 and then Get_Source_Unit
3097 (Errors.Table (E).Sptr.Ptr) /= Main_Unit))
3098 loop
3099 if Errors.Table (E).Deleted then
3100 E := Errors.Table (E).Next;
3102 else
3103 Write_Eol;
3104 Output_Source_Line
3105 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3106 Output_Error_Msgs (E);
3107 end if;
3108 end loop;
3110 -- If output to file, write extra copy of error summary to the
3111 -- output file, and then close it.
3113 if Full_List_File_Name /= null then
3114 Write_Error_Summary;
3115 Write_Max_Errors;
3116 Close_List_File_Access.all;
3117 Cancel_Special_Output;
3118 end if;
3119 end if;
3121 -- Verbose mode (error lines only with error flags). Normally this is
3122 -- ignored in full list mode, unless we are listing to a file, in which
3123 -- case we still generate -gnatv output to standard output.
3125 if Verbose_Mode
3126 and then (not Full_List or else Full_List_File_Name /= null)
3127 then
3128 Write_Eol;
3130 -- Output the header only when Main_Source_File is known
3132 if Main_Source_File > No_Source_File then
3133 Write_Header (Main_Source_File);
3134 end if;
3136 E := First_Error_Msg;
3138 -- Loop through error lines
3140 while E /= No_Error_Msg loop
3141 if Errors.Table (E).Deleted then
3142 E := Errors.Table (E).Next;
3143 else
3144 Write_Eol;
3145 Output_Source_Line
3146 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3147 Output_Error_Msgs (E);
3148 end if;
3149 end loop;
3150 end if;
3152 -- Output error summary if verbose or full list mode
3154 if Verbose_Mode or else Full_List then
3155 Write_Error_Summary;
3156 end if;
3158 if not Opt.JSON_Output then
3159 Write_Max_Errors;
3160 end if;
3162 -- Even though Warning_Info_Messages are a subclass of warnings, they
3163 -- must not be treated as errors when -gnatwe is in effect.
3165 if Warning_Mode = Treat_As_Error then
3166 declare
3167 Compile_Time_Pragma_Warnings : constant Int :=
3168 Count_Compile_Time_Pragma_Warnings;
3169 begin
3170 Total_Errors_Detected := Total_Errors_Detected + Warnings_Detected
3171 - Warning_Info_Messages - Compile_Time_Pragma_Warnings;
3172 Warnings_Detected :=
3173 Warning_Info_Messages + Compile_Time_Pragma_Warnings;
3174 end;
3175 end if;
3176 end Output_Messages;
3178 ------------------------
3179 -- Output_Source_Line --
3180 ------------------------
3182 procedure Output_Source_Line
3183 (L : Physical_Line_Number;
3184 Sfile : Source_File_Index;
3185 Errs : Boolean)
3187 S : Source_Ptr;
3188 C : Character;
3190 Line_Number_Output : Boolean := False;
3191 -- Set True once line number is output
3193 Empty_Line : Boolean := True;
3194 -- Set False if line includes at least one character
3196 begin
3197 if Sfile /= Current_Error_Source_File then
3198 Write_Str ("==============Error messages for ");
3200 case Sinput.File_Type (Sfile) is
3201 when Sinput.Src =>
3202 Write_Str ("source");
3204 when Sinput.Config =>
3205 Write_Str ("configuration pragmas");
3207 when Sinput.Def =>
3208 Write_Str ("symbol definition");
3210 when Sinput.Preproc =>
3211 Write_Str ("preprocessing data");
3212 end case;
3214 Write_Str (" file: ");
3215 Write_Name (Full_File_Name (Sfile));
3216 Write_Eol;
3218 if Num_SRef_Pragmas (Sfile) > 0 then
3219 Write_Str ("--------------Line numbers from file: ");
3220 Write_Name (Full_Ref_Name (Sfile));
3221 Write_Str (" (starting at line ");
3222 Write_Int (Int (First_Mapped_Line (Sfile)));
3223 Write_Char (')');
3224 Write_Eol;
3225 end if;
3227 Current_Error_Source_File := Sfile;
3228 end if;
3230 if Errs or List_Pragmas_Mode then
3231 Output_Line_Number (Physical_To_Logical (L, Sfile));
3232 Line_Number_Output := True;
3233 end if;
3235 S := Line_Start (L, Sfile);
3237 loop
3238 C := Source_Text (Sfile) (S);
3239 exit when C = ASCII.LF or else C = ASCII.CR or else C = EOF;
3241 -- Deal with matching entry in List_Pragmas table
3243 if Full_List
3244 and then List_Pragmas_Index <= List_Pragmas.Last
3245 and then S = List_Pragmas.Table (List_Pragmas_Index).Ploc
3246 then
3247 case List_Pragmas.Table (List_Pragmas_Index).Ptyp is
3248 when Page =>
3249 Write_Char (C);
3251 -- Ignore if on line with errors so that error flags
3252 -- get properly listed with the error line .
3254 if not Errs then
3255 Write_Char (ASCII.FF);
3256 end if;
3258 when List_On =>
3259 List_Pragmas_Mode := True;
3261 if not Line_Number_Output then
3262 Output_Line_Number (Physical_To_Logical (L, Sfile));
3263 Line_Number_Output := True;
3264 end if;
3266 Write_Char (C);
3268 when List_Off =>
3269 Write_Char (C);
3270 List_Pragmas_Mode := False;
3271 end case;
3273 List_Pragmas_Index := List_Pragmas_Index + 1;
3275 -- Normal case (no matching entry in List_Pragmas table)
3277 else
3278 if Errs or List_Pragmas_Mode then
3279 Write_Char (C);
3280 end if;
3281 end if;
3283 Empty_Line := False;
3284 S := S + 1;
3285 end loop;
3287 -- If we have output a source line, then add the line terminator, with
3288 -- training spaces preserved (so we output the line exactly as input).
3290 if Line_Number_Output then
3291 if Empty_Line then
3292 Write_Eol;
3293 else
3294 Write_Eol_Keep_Blanks;
3295 end if;
3296 end if;
3297 end Output_Source_Line;
3299 -----------------------------
3300 -- Remove_Warning_Messages --
3301 -----------------------------
3303 procedure Remove_Warning_Messages (N : Node_Id) is
3305 function Check_For_Warning (N : Node_Id) return Traverse_Result;
3306 -- This function checks one node for a possible warning message
3308 procedure Check_All_Warnings is new Traverse_Proc (Check_For_Warning);
3309 -- This defines the traversal operation
3311 -----------------------
3312 -- Check_For_Warning --
3313 -----------------------
3315 function Check_For_Warning (N : Node_Id) return Traverse_Result is
3316 Loc : constant Source_Ptr := Sloc (N);
3317 E : Error_Msg_Id;
3319 function To_Be_Removed (E : Error_Msg_Id) return Boolean;
3320 -- Returns True for a message that is to be removed. Also adjusts
3321 -- warning count appropriately.
3323 -------------------
3324 -- To_Be_Removed --
3325 -------------------
3327 function To_Be_Removed (E : Error_Msg_Id) return Boolean is
3328 begin
3329 if E /= No_Error_Msg
3331 -- Don't remove if location does not match
3333 and then Errors.Table (E).Optr.Ptr = Loc
3335 -- Don't remove if not warning/info message. Note that we do
3336 -- not remove style messages here. They are warning messages
3337 -- but not ones we want removed in this context.
3339 and then (Errors.Table (E).Warn
3340 or else
3341 Errors.Table (E).Warn_Runtime_Raise)
3343 -- Don't remove unconditional messages
3345 and then not Errors.Table (E).Uncond
3346 then
3347 if Errors.Table (E).Warn then
3348 Warnings_Detected := Warnings_Detected - 1;
3349 end if;
3351 if Errors.Table (E).Info then
3352 Warning_Info_Messages := Warning_Info_Messages - 1;
3353 end if;
3355 -- When warning about a runtime exception has been escalated
3356 -- into error, the starting message has increased the total
3357 -- errors counter, so here we decrease this counter.
3359 if Errors.Table (E).Warn_Runtime_Raise
3360 and then not Errors.Table (E).Msg_Cont
3361 and then Warning_Mode = Treat_Run_Time_Warnings_As_Errors
3362 then
3363 Total_Errors_Detected := Total_Errors_Detected - 1;
3364 end if;
3366 return True;
3368 -- No removal required
3370 else
3371 return False;
3372 end if;
3373 end To_Be_Removed;
3375 -- Start of processing for Check_For_Warnings
3377 begin
3378 while To_Be_Removed (First_Error_Msg) loop
3379 First_Error_Msg := Errors.Table (First_Error_Msg).Next;
3380 end loop;
3382 if First_Error_Msg = No_Error_Msg then
3383 Last_Error_Msg := No_Error_Msg;
3384 end if;
3386 E := First_Error_Msg;
3387 while E /= No_Error_Msg loop
3388 while To_Be_Removed (Errors.Table (E).Next) loop
3389 Errors.Table (E).Next :=
3390 Errors.Table (Errors.Table (E).Next).Next;
3392 if Errors.Table (E).Next = No_Error_Msg then
3393 Last_Error_Msg := E;
3394 end if;
3395 end loop;
3397 E := Errors.Table (E).Next;
3398 end loop;
3400 -- Warnings may have been posted on subexpressions of original tree
3402 if Nkind (N) = N_Raise_Constraint_Error
3403 and then Is_Rewrite_Substitution (N)
3404 and then No (Condition (N))
3405 then
3406 Check_All_Warnings (Original_Node (N));
3407 end if;
3409 return OK;
3410 end Check_For_Warning;
3412 -- Start of processing for Remove_Warning_Messages
3414 begin
3415 if Warnings_Detected /= 0 then
3416 Check_All_Warnings (N);
3417 end if;
3418 end Remove_Warning_Messages;
3420 procedure Remove_Warning_Messages (L : List_Id) is
3421 Stat : Node_Id;
3422 begin
3423 Stat := First (L);
3424 while Present (Stat) loop
3425 Remove_Warning_Messages (Stat);
3426 Next (Stat);
3427 end loop;
3428 end Remove_Warning_Messages;
3430 ----------------------
3431 -- Adjust_Name_Case --
3432 ----------------------
3434 procedure Adjust_Name_Case
3435 (Buf : in out Bounded_String;
3436 Loc : Source_Ptr)
3438 Src_Ind : constant Source_File_Index := Get_Source_File_Index (Loc);
3439 Sbuffer : Source_Buffer_Ptr;
3440 Ref_Ptr : Integer;
3441 Src_Ptr : Source_Ptr;
3443 begin
3444 -- We have an all lower case name from Namet, and now we want to set
3445 -- the appropriate case. If possible we copy the actual casing from
3446 -- the source. If not we use standard identifier casing.
3448 Ref_Ptr := 1;
3449 Src_Ptr := Loc;
3451 -- For standard locations, always use mixed case
3453 if Loc <= No_Location then
3454 Set_Casing (Buf, Mixed_Case);
3456 else
3457 -- Determine if the reference we are dealing with corresponds to text
3458 -- at the point of the error reference. This will often be the case
3459 -- for simple identifier references, and is the case where we can
3460 -- copy the casing from the source.
3462 Sbuffer := Source_Text (Src_Ind);
3464 while Ref_Ptr <= Buf.Length loop
3465 exit when
3466 Fold_Lower (Sbuffer (Src_Ptr)) /=
3467 Fold_Lower (Buf.Chars (Ref_Ptr));
3468 Ref_Ptr := Ref_Ptr + 1;
3469 Src_Ptr := Src_Ptr + 1;
3470 end loop;
3472 -- If we get through the loop without a mismatch, then output the
3473 -- name the way it is cased in the source program.
3475 if Ref_Ptr > Buf.Length then
3476 Src_Ptr := Loc;
3478 for J in 1 .. Buf.Length loop
3479 Buf.Chars (J) := Sbuffer (Src_Ptr);
3480 Src_Ptr := Src_Ptr + 1;
3481 end loop;
3483 -- Otherwise set the casing using the default identifier casing
3485 else
3486 Set_Casing (Buf, Identifier_Casing (Src_Ind));
3487 end if;
3488 end if;
3489 end Adjust_Name_Case;
3491 ---------------------------
3492 -- Set_Identifier_Casing --
3493 ---------------------------
3495 procedure Set_Identifier_Casing
3496 (Identifier_Name : System.Address;
3497 File_Name : System.Address)
3499 Ident : constant Big_String_Ptr := To_Big_String_Ptr (Identifier_Name);
3500 File : constant Big_String_Ptr := To_Big_String_Ptr (File_Name);
3501 Flen : Natural;
3503 Desired_Case : Casing_Type := Mixed_Case;
3504 -- Casing required for result. Default value of Mixed_Case is used if
3505 -- for some reason we cannot find the right file name in the table.
3507 begin
3508 -- Get length of file name
3510 Flen := 0;
3511 while File (Flen + 1) /= ASCII.NUL loop
3512 Flen := Flen + 1;
3513 end loop;
3515 -- Loop through file names to find matching one. This is a bit slow, but
3516 -- we only do it in error situations so it is not so terrible. Note that
3517 -- if the loop does not exit, then the desired case will be left set to
3518 -- Mixed_Case, this can happen if the name was not in canonical form.
3520 for J in 1 .. Last_Source_File loop
3521 Get_Name_String (Full_Debug_Name (J));
3523 if Name_Len = Flen
3524 and then Name_Buffer (1 .. Name_Len) = String (File (1 .. Flen))
3525 then
3526 Desired_Case := Identifier_Casing (J);
3527 exit;
3528 end if;
3529 end loop;
3531 -- Copy identifier as given to Name_Buffer
3533 for J in Name_Buffer'Range loop
3534 Name_Buffer (J) := Ident (J);
3536 if Name_Buffer (J) = ASCII.NUL then
3537 Name_Len := J - 1;
3538 exit;
3539 end if;
3540 end loop;
3542 Set_Casing (Desired_Case);
3543 end Set_Identifier_Casing;
3545 -----------------------
3546 -- Set_Ignore_Errors --
3547 -----------------------
3549 procedure Set_Ignore_Errors (To : Boolean) is
3550 begin
3551 Errors_Must_Be_Ignored := To;
3552 end Set_Ignore_Errors;
3554 ------------------------------
3555 -- Set_Msg_Insertion_Column --
3556 ------------------------------
3558 procedure Set_Msg_Insertion_Column is
3559 begin
3560 if RM_Column_Check then
3561 Set_Msg_Str (" in column ");
3562 Set_Msg_Int (Int (Error_Msg_Col) + 1);
3563 end if;
3564 end Set_Msg_Insertion_Column;
3566 ----------------------------
3567 -- Set_Msg_Insertion_Node --
3568 ----------------------------
3570 procedure Set_Msg_Insertion_Node is
3571 K : Node_Kind;
3573 begin
3574 Suppress_Message :=
3575 Error_Msg_Node_1 = Error
3576 or else Error_Msg_Node_1 = Any_Type;
3578 if Error_Msg_Node_1 = Empty then
3579 Set_Msg_Blank_Conditional;
3580 Set_Msg_Str ("<empty>");
3582 elsif Error_Msg_Node_1 = Error then
3583 Set_Msg_Blank;
3584 Set_Msg_Str ("<error>");
3586 elsif Error_Msg_Node_1 = Standard_Void_Type then
3587 Set_Msg_Blank;
3588 Set_Msg_Str ("procedure name");
3590 elsif Nkind (Error_Msg_Node_1) in N_Entity
3591 and then Ekind (Error_Msg_Node_1) = E_Anonymous_Access_Subprogram_Type
3592 then
3593 Set_Msg_Blank;
3594 Set_Msg_Str ("access to subprogram");
3596 else
3597 Set_Msg_Blank_Conditional;
3599 -- Output name
3601 K := Nkind (Error_Msg_Node_1);
3603 -- If we have operator case, skip quotes since name of operator
3604 -- itself will supply the required quotations. An operator can be an
3605 -- applied use in an expression or an explicit operator symbol, or an
3606 -- identifier whose name indicates it is an operator.
3608 if K in N_Op
3609 or else K = N_Operator_Symbol
3610 or else K = N_Defining_Operator_Symbol
3611 or else ((K = N_Identifier or else K = N_Defining_Identifier)
3612 and then Is_Operator_Name (Chars (Error_Msg_Node_1)))
3613 then
3614 Set_Msg_Node (Error_Msg_Node_1);
3616 -- Normal case, not an operator, surround with quotes
3618 else
3619 Set_Msg_Quote;
3620 Set_Qualification (Error_Msg_Qual_Level, Error_Msg_Node_1);
3621 Set_Msg_Node (Error_Msg_Node_1);
3622 Set_Msg_Quote;
3623 end if;
3624 end if;
3626 -- The following assignment ensures that further ampersand insertion
3627 -- characters will correspond to the Error_Msg_Node_# parameter.
3629 Error_Msg_Node_1 := Error_Msg_Node_2;
3630 Error_Msg_Node_2 := Error_Msg_Node_3;
3631 Error_Msg_Node_3 := Error_Msg_Node_4;
3632 Error_Msg_Node_4 := Error_Msg_Node_5;
3633 Error_Msg_Node_5 := Error_Msg_Node_6;
3634 end Set_Msg_Insertion_Node;
3636 --------------------------------------
3637 -- Set_Msg_Insertion_Type_Reference --
3638 --------------------------------------
3640 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr) is
3641 Ent : Entity_Id;
3643 begin
3644 Set_Msg_Blank;
3646 if Error_Msg_Node_1 = Standard_Void_Type then
3647 Set_Msg_Str ("package or procedure name");
3648 return;
3650 elsif Error_Msg_Node_1 = Standard_Exception_Type then
3651 Set_Msg_Str ("exception name");
3652 return;
3654 elsif Error_Msg_Node_1 = Any_Array
3655 or else Error_Msg_Node_1 = Any_Boolean
3656 or else Error_Msg_Node_1 = Any_Character
3657 or else Error_Msg_Node_1 = Any_Composite
3658 or else Error_Msg_Node_1 = Any_Discrete
3659 or else Error_Msg_Node_1 = Any_Fixed
3660 or else Error_Msg_Node_1 = Any_Integer
3661 or else Error_Msg_Node_1 = Any_Modular
3662 or else Error_Msg_Node_1 = Any_Numeric
3663 or else Error_Msg_Node_1 = Any_Real
3664 or else Error_Msg_Node_1 = Any_Scalar
3665 or else Error_Msg_Node_1 = Any_String
3666 then
3667 Get_Unqualified_Decoded_Name_String (Chars (Error_Msg_Node_1));
3668 Set_Msg_Name_Buffer;
3669 return;
3671 elsif Error_Msg_Node_1 = Universal_Integer then
3672 Set_Msg_Str ("type universal integer");
3673 return;
3675 elsif Error_Msg_Node_1 = Universal_Real then
3676 Set_Msg_Str ("type universal real");
3677 return;
3679 elsif Error_Msg_Node_1 = Universal_Fixed then
3680 Set_Msg_Str ("type universal fixed");
3681 return;
3683 elsif Error_Msg_Node_1 = Universal_Access then
3684 Set_Msg_Str ("type universal access");
3685 return;
3686 end if;
3688 -- Special case of anonymous array
3690 if Nkind (Error_Msg_Node_1) in N_Entity
3691 and then Is_Array_Type (Error_Msg_Node_1)
3692 and then Present (Related_Array_Object (Error_Msg_Node_1))
3693 then
3694 Set_Msg_Str ("type of ");
3695 Set_Msg_Node (Related_Array_Object (Error_Msg_Node_1));
3696 Set_Msg_Str (" declared");
3697 Set_Msg_Insertion_Line_Number
3698 (Sloc (Related_Array_Object (Error_Msg_Node_1)), Flag);
3699 return;
3700 end if;
3702 -- If we fall through, it is not a special case, so first output
3703 -- the name of the type, preceded by private for a private type
3705 if Is_Private_Type (Error_Msg_Node_1) then
3706 Set_Msg_Str ("private type ");
3707 else
3708 Set_Msg_Str ("type ");
3709 end if;
3711 Ent := Error_Msg_Node_1;
3713 if Is_Internal_Name (Chars (Ent)) then
3714 Unwind_Internal_Type (Ent);
3715 end if;
3717 -- Types in Standard are displayed as "Standard.name"
3719 if Sloc (Ent) <= Standard_Location then
3720 Set_Msg_Quote;
3721 Set_Msg_Str ("Standard.");
3722 Set_Msg_Node (Ent);
3723 Add_Class;
3724 Set_Msg_Quote;
3726 -- Types in other language defined units are displayed as
3727 -- "package-name.type-name"
3729 elsif Is_Predefined_Unit (Get_Source_Unit (Ent)) then
3730 Get_Unqualified_Decoded_Name_String
3731 (Unit_Name (Get_Source_Unit (Ent)));
3732 Name_Len := Name_Len - 2;
3733 Set_Msg_Blank_Conditional;
3734 Set_Msg_Quote;
3735 Set_Casing (Mixed_Case);
3736 Set_Msg_Name_Buffer;
3737 Set_Msg_Char ('.');
3738 Set_Casing (Mixed_Case);
3739 Set_Msg_Node (Ent);
3740 Add_Class;
3741 Set_Msg_Quote;
3743 -- All other types display as "type name" defined at line xxx
3744 -- possibly qualified if qualification is requested.
3746 else
3747 Set_Msg_Quote;
3748 Set_Qualification (Error_Msg_Qual_Level, Ent);
3749 Set_Msg_Node (Ent);
3750 Add_Class;
3752 -- If we did not print a name (e.g. in the case of an anonymous
3753 -- subprogram type), there is no name to print, so remove quotes.
3755 if Buffer_Ends_With ('"') then
3756 Buffer_Remove ('"');
3757 else
3758 Set_Msg_Quote;
3759 end if;
3760 end if;
3762 -- If the original type did not come from a predefined file, add the
3763 -- location where the type was defined.
3765 if Sloc (Error_Msg_Node_1) > Standard_Location
3766 and then
3767 not Is_Predefined_Unit (Get_Source_Unit (Error_Msg_Node_1))
3768 then
3769 Get_Name_String (Unit_File_Name (Get_Source_Unit (Error_Msg_Node_1)));
3770 Set_Msg_Str (" defined");
3771 Set_Msg_Insertion_Line_Number (Sloc (Error_Msg_Node_1), Flag);
3773 -- If it did come from a predefined file, deal with the case where
3774 -- this was a file with a generic instantiation from elsewhere.
3776 else
3777 if Sloc (Error_Msg_Node_1) > Standard_Location then
3778 declare
3779 Iloc : constant Source_Ptr :=
3780 Instantiation_Location (Sloc (Error_Msg_Node_1));
3782 begin
3783 if Iloc /= No_Location
3784 and then not Suppress_Instance_Location
3785 then
3786 Set_Msg_Str (" from instance");
3787 Set_Msg_Insertion_Line_Number (Iloc, Flag);
3788 end if;
3789 end;
3790 end if;
3791 end if;
3792 end Set_Msg_Insertion_Type_Reference;
3794 ---------------------------------
3795 -- Set_Msg_Insertion_Unit_Name --
3796 ---------------------------------
3798 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True) is
3799 begin
3800 if Error_Msg_Unit_1 = No_Unit_Name then
3801 null;
3803 elsif Error_Msg_Unit_1 = Error_Unit_Name then
3804 Set_Msg_Blank;
3805 Set_Msg_Str ("<error>");
3807 else
3808 Get_Unit_Name_String (Global_Name_Buffer, Error_Msg_Unit_1, Suffix);
3809 Set_Msg_Blank;
3810 Set_Msg_Quote;
3811 Set_Msg_Name_Buffer;
3812 Set_Msg_Quote;
3813 end if;
3815 -- The following assignment ensures that a second percent insertion
3816 -- character will correspond to the Error_Msg_Unit_2 parameter.
3818 Error_Msg_Unit_1 := Error_Msg_Unit_2;
3819 end Set_Msg_Insertion_Unit_Name;
3821 ------------------
3822 -- Set_Msg_Node --
3823 ------------------
3825 procedure Set_Msg_Node (Node : Node_Id) is
3826 Loc : Source_Ptr;
3827 Ent : Entity_Id;
3828 Nam : Name_Id;
3830 begin
3831 case Nkind (Node) is
3832 when N_Designator =>
3833 Set_Msg_Node (Name (Node));
3834 Set_Msg_Char ('.');
3835 Set_Msg_Node (Identifier (Node));
3836 return;
3838 when N_Defining_Program_Unit_Name =>
3839 Set_Msg_Node (Name (Node));
3840 Set_Msg_Char ('.');
3841 Set_Msg_Node (Defining_Identifier (Node));
3842 return;
3844 when N_Expanded_Name
3845 | N_Selected_Component
3847 Set_Msg_Node (Prefix (Node));
3848 Set_Msg_Char ('.');
3849 Set_Msg_Node (Selector_Name (Node));
3850 return;
3852 when others =>
3853 null;
3854 end case;
3856 -- The only remaining possibilities are identifiers, defining
3857 -- identifiers, pragmas, and pragma argument associations.
3859 if Nkind (Node) = N_Pragma then
3860 Nam := Pragma_Name (Node);
3861 Loc := Sloc (Node);
3863 -- The other cases have Chars fields
3865 -- First deal with internal names, which generally represent something
3866 -- gone wrong. First attempt: if this is a rewritten node that rewrites
3867 -- something with a Chars field that is not an internal name, use that.
3869 elsif Is_Internal_Name (Chars (Node))
3870 and then Nkind (Original_Node (Node)) in N_Has_Chars
3871 and then not Is_Internal_Name (Chars (Original_Node (Node)))
3872 then
3873 Nam := Chars (Original_Node (Node));
3874 Loc := Sloc (Original_Node (Node));
3876 -- Another shot for internal names, in the case of internal type names,
3877 -- we try to find a reasonable representation for the external name.
3879 elsif Is_Internal_Name (Chars (Node))
3880 and then
3881 ((Is_Entity_Name (Node)
3882 and then Present (Entity (Node))
3883 and then Is_Type (Entity (Node)))
3884 or else
3885 (Nkind (Node) = N_Defining_Identifier and then Is_Type (Node)))
3886 then
3887 if Nkind (Node) = N_Identifier then
3888 Ent := Entity (Node);
3889 else
3890 Ent := Node;
3891 end if;
3893 Loc := Sloc (Ent);
3895 -- If the type is the designated type of an access_to_subprogram,
3896 -- then there is no name to provide in the call.
3898 if Ekind (Ent) = E_Subprogram_Type then
3899 return;
3901 -- Otherwise, we will be able to find some kind of name to output
3903 else
3904 Unwind_Internal_Type (Ent);
3905 Nam := Chars (Ent);
3906 end if;
3908 -- If not internal name, or if we could not find a reasonable possible
3909 -- substitution for the internal name, just use name in Chars field.
3911 else
3912 Nam := Chars (Node);
3913 Loc := Sloc (Node);
3914 end if;
3916 -- At this stage, the name to output is in Nam
3918 Get_Unqualified_Decoded_Name_String (Nam);
3920 -- Remove trailing upper case letters from the name (useful for
3921 -- dealing with some cases of internal names).
3923 while Name_Len > 1 and then Name_Buffer (Name_Len) in 'A' .. 'Z' loop
3924 Name_Len := Name_Len - 1;
3925 end loop;
3927 -- If we have any of the names from standard that start with the
3928 -- characters "any " (e.g. Any_Type), then kill the message since
3929 -- almost certainly it is a junk cascaded message.
3931 if Name_Len > 4
3932 and then Name_Buffer (1 .. 4) = "any "
3933 then
3934 Kill_Message := True;
3935 end if;
3937 -- If we still have an internal name, kill the message (will only
3938 -- work if we already had errors!)
3940 if Is_Internal_Name then
3941 Kill_Message := True;
3942 end if;
3943 -- Remaining step is to adjust casing and possibly add 'Class
3945 Adjust_Name_Case (Global_Name_Buffer, Loc);
3946 Set_Msg_Name_Buffer;
3947 Add_Class;
3948 end Set_Msg_Node;
3950 ------------------
3951 -- Set_Msg_Text --
3952 ------------------
3954 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is
3955 C : Character; -- Current character
3956 P : Natural; -- Current index;
3958 procedure Skip_Msg_Insertion_Warning (C : Character);
3959 -- Skip the ? ?? ?x? ?*? ?$? insertion sequences (and the same
3960 -- sequences using < instead of ?). The caller has already bumped
3961 -- the pointer past the initial ? or < and C is set to this initial
3962 -- character (? or <). This procedure skips past the rest of the
3963 -- sequence. We do not need to set Msg_Insertion_Char, since this
3964 -- was already done during the message prescan.
3965 -- No validity check is performed as the insertion sequence is
3966 -- supposed to be sane. See Prescan_Message.Parse_Message_Class in
3967 -- erroutc.adb for the validity checks.
3969 --------------------------------
3970 -- Skip_Msg_Insertion_Warning --
3971 --------------------------------
3973 procedure Skip_Msg_Insertion_Warning (C : Character) is
3974 begin
3975 if P <= Text'Last and then Text (P) = C then
3976 P := P + 1;
3978 elsif P < Text'Last and then Text (P + 1) = C
3979 and then Text (P) in 'a' .. 'z' | '*' | '$'
3980 then
3981 P := P + 2;
3983 elsif P + 1 < Text'Last and then Text (P + 2) = C
3984 and then Text (P) in '.' | '_'
3985 and then Text (P + 1) in 'a' .. 'z'
3986 then
3987 P := P + 3;
3988 end if;
3989 end Skip_Msg_Insertion_Warning;
3991 -- Start of processing for Set_Msg_Text
3993 begin
3994 Manual_Quote_Mode := False;
3995 Msglen := 0;
3996 Flag_Source := Get_Source_File_Index (Flag);
3998 -- Skip info: at start, we have recorded this in Is_Info_Msg, and this
3999 -- will be used (Info field in error message object) to put back the
4000 -- string when it is printed. We need to do this, or we get confused
4001 -- with instantiation continuations.
4003 if Text'Length > 6
4004 and then Text (Text'First .. Text'First + 5) = "info: "
4005 then
4006 P := Text'First + 6;
4007 else
4008 P := Text'First;
4009 end if;
4011 -- Loop through characters of message
4013 while P <= Text'Last loop
4014 C := Text (P);
4015 P := P + 1;
4017 -- Check for insertion character or sequence
4019 case C is
4020 when '%' =>
4021 if P <= Text'Last and then Text (P) = '%' then
4022 P := P + 1;
4023 Set_Msg_Insertion_Name_Literal;
4024 else
4025 Set_Msg_Insertion_Name;
4026 end if;
4028 when '$' =>
4029 if P <= Text'Last and then Text (P) = '$' then
4030 P := P + 1;
4031 Set_Msg_Insertion_Unit_Name (Suffix => False);
4032 else
4033 Set_Msg_Insertion_Unit_Name;
4034 end if;
4036 when '{' =>
4037 Set_Msg_Insertion_File_Name;
4039 when '}' =>
4040 Set_Msg_Insertion_Type_Reference (Flag);
4042 when '*' =>
4043 Set_Msg_Insertion_Reserved_Name;
4045 when '&' =>
4046 Set_Msg_Insertion_Node;
4048 when '#' =>
4049 Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag);
4051 when '\' =>
4052 Continuation := True;
4054 if P <= Text'Last and then Text (P) = '\' then
4055 Continuation_New_Line := True;
4056 P := P + 1;
4057 end if;
4059 when '@' =>
4060 Set_Msg_Insertion_Column;
4062 when '>' =>
4063 Set_Msg_Insertion_Run_Time_Name;
4065 when '^' =>
4066 Set_Msg_Insertion_Uint;
4068 when '`' =>
4069 Manual_Quote_Mode := not Manual_Quote_Mode;
4070 Set_Msg_Char ('"');
4072 when '!' =>
4073 null; -- already dealt with
4075 when '?' =>
4076 Skip_Msg_Insertion_Warning ('?');
4078 when '<' =>
4079 Skip_Msg_Insertion_Warning ('<');
4081 when '|' =>
4082 null; -- already dealt with
4084 when ''' =>
4085 Set_Msg_Char (Text (P));
4086 P := P + 1;
4088 when '~' =>
4089 Set_Msg_Str (Error_Msg_String (1 .. Error_Msg_Strlen));
4091 -- Upper case letter
4093 when 'A' .. 'Z' =>
4095 -- Start of reserved word if two or more
4097 if P <= Text'Last and then Text (P) in 'A' .. 'Z' then
4098 P := P - 1;
4099 Set_Msg_Insertion_Reserved_Word (Text, P);
4101 -- Single upper case letter is just inserted
4103 else
4104 Set_Msg_Char (C);
4105 end if;
4107 -- '[' (will be/would have been raised at run time)
4109 when '[' =>
4111 -- Switch the message from a warning to an error if the flag
4112 -- -gnatwE is specified to treat run-time exception warnings
4113 -- as errors.
4115 if Is_Warning_Msg
4116 and then Warning_Mode = Treat_Run_Time_Warnings_As_Errors
4117 then
4118 Is_Warning_Msg := False;
4119 Is_Runtime_Raise := True;
4120 end if;
4122 if Is_Warning_Msg then
4123 Set_Msg_Str ("will be raised at run time");
4124 else
4125 Set_Msg_Str ("would have been raised at run time");
4126 end if;
4128 -- ']' (may be/might have been raised at run time)
4130 when ']' =>
4131 if Is_Warning_Msg then
4132 Set_Msg_Str ("may be raised at run time");
4133 else
4134 Set_Msg_Str ("might have been raised at run time");
4135 end if;
4137 -- Normal character with no special treatment
4139 when others =>
4140 Set_Msg_Char (C);
4141 end case;
4142 end loop;
4143 end Set_Msg_Text;
4145 ----------------
4146 -- Set_Posted --
4147 ----------------
4149 procedure Set_Posted (N : Node_Id) is
4150 P : Node_Id;
4152 begin
4153 if Is_Serious_Error then
4155 -- We always set Error_Posted on the node itself
4157 Set_Error_Posted (N);
4159 -- If it is a subexpression, then set Error_Posted on parents up to
4160 -- and including the first non-subexpression construct. This helps
4161 -- avoid cascaded error messages within a single expression.
4163 P := N;
4164 loop
4165 P := Parent (P);
4166 exit when No (P);
4167 Set_Error_Posted (P);
4168 exit when Nkind (P) not in N_Subexpr;
4169 end loop;
4171 if Nkind (P) in N_Pragma_Argument_Association
4172 | N_Component_Association
4173 | N_Discriminant_Association
4174 | N_Generic_Association
4175 | N_Parameter_Association
4176 then
4177 Set_Error_Posted (Parent (P));
4178 end if;
4180 -- A special check, if we just posted an error on an attribute
4181 -- definition clause, then also set the entity involved as posted.
4182 -- For example, this stops complaining about the alignment after
4183 -- complaining about the size, which is likely to be useless.
4185 if Nkind (P) = N_Attribute_Definition_Clause then
4186 if Is_Entity_Name (Name (P)) then
4187 Set_Error_Posted (Entity (Name (P)));
4188 end if;
4189 end if;
4190 end if;
4191 end Set_Posted;
4193 -----------------------
4194 -- Set_Qualification --
4195 -----------------------
4197 procedure Set_Qualification (N : Nat; E : Entity_Id) is
4198 begin
4199 if N /= 0 and then Scope (E) /= Standard_Standard then
4200 Set_Qualification (N - 1, Scope (E));
4201 Set_Msg_Node (Scope (E));
4202 Set_Msg_Char ('.');
4203 end if;
4204 end Set_Qualification;
4206 ------------------------
4207 -- Special_Msg_Delete --
4208 ------------------------
4210 -- Is it really right to have all this specialized knowledge in errout?
4212 function Special_Msg_Delete
4213 (Msg : String;
4214 N : Node_Or_Entity_Id;
4215 E : Node_Or_Entity_Id) return Boolean
4217 begin
4218 -- Never delete messages in -gnatdO mode
4220 if Debug_Flag_OO then
4221 return False;
4223 -- Processing for "Size too small" messages
4225 elsif Is_Size_Too_Small_Message (Msg) then
4227 -- Suppress "size too small" errors in CodePeer mode, since code may
4228 -- be analyzed in a different configuration than the one used for
4229 -- compilation. Even when the configurations match, this message
4230 -- may be issued on correct code, because pragma Pack is ignored
4231 -- in CodePeer mode.
4233 if CodePeer_Mode then
4234 return True;
4236 -- When a size is wrong for a frozen type there is no explicit size
4237 -- clause, and other errors have occurred, suppress the message,
4238 -- since it is likely that this size error is a cascaded result of
4239 -- other errors. The reason we eliminate unfrozen types is that
4240 -- messages issued before the freeze type are for sure OK.
4242 elsif Nkind (N) in N_Entity
4243 and then Is_Frozen (E)
4244 and then Serious_Errors_Detected > 0
4245 and then Nkind (N) /= N_Component_Clause
4246 and then Nkind (Parent (N)) /= N_Component_Clause
4247 and then
4248 No (Get_Attribute_Definition_Clause (E, Attribute_Size))
4249 and then
4250 No (Get_Attribute_Definition_Clause (E, Attribute_Object_Size))
4251 and then
4252 No (Get_Attribute_Definition_Clause (E, Attribute_Value_Size))
4253 then
4254 return True;
4255 end if;
4256 end if;
4258 -- All special tests complete, so go ahead with message
4260 return False;
4261 end Special_Msg_Delete;
4263 -----------------
4264 -- SPARK_Msg_N --
4265 -----------------
4267 procedure SPARK_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
4268 begin
4269 if SPARK_Mode /= Off then
4270 Error_Msg_N (Msg, N);
4271 end if;
4272 end SPARK_Msg_N;
4274 ------------------
4275 -- SPARK_Msg_NE --
4276 ------------------
4278 procedure SPARK_Msg_NE
4279 (Msg : String;
4280 N : Node_Or_Entity_Id;
4281 E : Node_Or_Entity_Id)
4283 begin
4284 if SPARK_Mode /= Off then
4285 Error_Msg_NE (Msg, N, E);
4286 end if;
4287 end SPARK_Msg_NE;
4289 --------------------------
4290 -- Unwind_Internal_Type --
4291 --------------------------
4293 procedure Unwind_Internal_Type (Ent : in out Entity_Id) is
4294 Derived : Boolean := False;
4295 Mchar : Character;
4296 Old_Ent : Entity_Id;
4298 begin
4299 -- Undo placement of a quote, since we will put it back later
4301 Mchar := Msg_Buffer (Msglen);
4303 if Mchar = '"' then
4304 Msglen := Msglen - 1;
4305 end if;
4307 -- The loop here deals with recursive types, we are trying to find a
4308 -- related entity that is not an implicit type. Note that the check with
4309 -- Old_Ent stops us from getting "stuck". Also, we don't output the
4310 -- "type derived from" message more than once in the case where we climb
4311 -- up multiple levels.
4313 Find : loop
4314 Old_Ent := Ent;
4316 -- Implicit access type, use directly designated type In Ada 2005,
4317 -- the designated type may be an anonymous access to subprogram, in
4318 -- which case we can only point to its definition.
4320 if Is_Access_Type (Ent) then
4321 if Ekind (Ent) = E_Access_Subprogram_Type
4322 or else Ekind (Ent) = E_Anonymous_Access_Subprogram_Type
4323 or else Is_Access_Protected_Subprogram_Type (Ent)
4324 then
4325 Ent := Directly_Designated_Type (Ent);
4327 if not Comes_From_Source (Ent) then
4328 if Buffer_Ends_With ("type ") then
4329 Buffer_Remove ("type ");
4330 end if;
4331 end if;
4333 if Ekind (Ent) = E_Function then
4334 Set_Msg_Str ("access to function ");
4335 elsif Ekind (Ent) = E_Procedure then
4336 Set_Msg_Str ("access to procedure ");
4337 else
4338 Set_Msg_Str ("access to subprogram");
4339 end if;
4341 exit Find;
4343 -- Type is access to object, named or anonymous
4345 else
4346 Set_Msg_Str ("access to ");
4347 Ent := Directly_Designated_Type (Ent);
4348 end if;
4350 -- Classwide type
4352 elsif Is_Class_Wide_Type (Ent) then
4353 Class_Flag := True;
4354 Ent := Root_Type (Ent);
4356 -- Use base type if this is a subtype
4358 elsif Ent /= Base_Type (Ent) then
4359 Buffer_Remove ("type ");
4361 -- Avoid duplication "subtype of subtype of", and also replace
4362 -- "derived from subtype of" simply by "derived from"
4364 if not Buffer_Ends_With ("subtype of ")
4365 and then not Buffer_Ends_With ("derived from ")
4366 then
4367 Set_Msg_Str ("subtype of ");
4368 end if;
4370 Ent := Base_Type (Ent);
4372 -- If this is a base type with a first named subtype, use the first
4373 -- named subtype instead. This is not quite accurate in all cases,
4374 -- but it makes too much noise to be accurate and add 'Base in all
4375 -- cases. Note that we only do this is the first named subtype is not
4376 -- itself an internal name. This avoids the obvious loop (subtype ->
4377 -- basetype -> subtype) which would otherwise occur).
4379 else
4380 declare
4381 FST : constant Entity_Id := First_Subtype (Ent);
4383 begin
4384 if not Is_Internal_Name (Chars (FST)) then
4385 Ent := FST;
4386 exit Find;
4388 -- Otherwise use root type
4390 else
4391 if not Derived then
4392 Buffer_Remove ("type ");
4394 -- Test for "subtype of type derived from" which seems
4395 -- excessive and is replaced by "type derived from".
4397 Buffer_Remove ("subtype of");
4399 -- Avoid duplicated "type derived from type derived from"
4401 if not Buffer_Ends_With ("type derived from ") then
4402 Set_Msg_Str ("type derived from ");
4403 end if;
4405 Derived := True;
4406 end if;
4407 end if;
4408 end;
4410 Ent := Etype (Ent);
4411 end if;
4413 -- If we are stuck in a loop, get out and settle for the internal
4414 -- name after all. In this case we set to kill the message if it is
4415 -- not the first error message (we really try hard not to show the
4416 -- dirty laundry of the implementation to the poor user).
4418 if Ent = Old_Ent then
4419 Kill_Message := True;
4420 exit Find;
4421 end if;
4423 -- Get out if we finally found a non-internal name to use
4425 exit Find when not Is_Internal_Name (Chars (Ent));
4426 end loop Find;
4428 if Mchar = '"' then
4429 Set_Msg_Char ('"');
4430 end if;
4431 end Unwind_Internal_Type;
4433 --------------------
4434 -- Warn_Insertion --
4435 --------------------
4437 function Warn_Insertion return String is
4438 begin
4439 if Warning_Msg_Char = "? " then
4440 return "??";
4441 elsif Warning_Msg_Char = " " then
4442 return "?";
4443 elsif Warning_Msg_Char (2) = ' ' then
4444 return '?' & Warning_Msg_Char (1) & '?';
4445 else
4446 return '?' & Warning_Msg_Char & '?';
4447 end if;
4448 end Warn_Insertion;
4450 end Errout;