[Ada] Improve error messages for occurrence of GNAT extensions without -gnatX
[official-gcc.git] / gcc / ada / errout.adb
blob101aed435e6ad967b991026a557c399a561911d7
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-2022, 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 Uname; use Uname;
56 package body Errout is
58 Errors_Must_Be_Ignored : Boolean := False;
59 -- Set to True by procedure Set_Ignore_Errors (True), when calls to error
60 -- message procedures should be ignored (when parsing irrelevant text in
61 -- sources being preprocessed).
63 Finalize_Called : Boolean := False;
64 -- Set True if the Finalize routine has been called
66 Record_Compilation_Errors : Boolean := False;
67 -- Record that a compilation error was witnessed during a given phase of
68 -- analysis for gnat2why. This is needed as Warning_Mode is modified twice
69 -- in gnat2why, hence Erroutc.Compilation_Errors can only return a suitable
70 -- value for each phase of analysis separately. This is updated at each
71 -- call to Compilation_Errors.
73 Warn_On_Instance : Boolean;
74 -- Flag set true for warning message to be posted on instance
76 ------------------------------------
77 -- Table of Non-Instance Messages --
78 ------------------------------------
80 -- This table contains an entry for every error message processed by the
81 -- Error_Msg routine that is not posted on generic (or inlined) instance.
82 -- As explained in further detail in the Error_Msg procedure body, this
83 -- table is used to avoid posting redundant messages on instances.
85 type NIM_Record is record
86 Msg : String_Ptr;
87 Loc : Source_Ptr;
88 end record;
89 -- Type used to store text and location of one message
91 package Non_Instance_Msgs is new Table.Table (
92 Table_Component_Type => NIM_Record,
93 Table_Index_Type => Int,
94 Table_Low_Bound => 1,
95 Table_Initial => 100,
96 Table_Increment => 100,
97 Table_Name => "Non_Instance_Msgs");
99 -----------------------
100 -- Local Subprograms --
101 -----------------------
103 procedure Error_Msg_Internal
104 (Msg : String;
105 Span : Source_Span;
106 Opan : Source_Span;
107 Msg_Cont : Boolean;
108 Node : Node_Id);
109 -- This is the low-level routine used to post messages after dealing with
110 -- the issue of messages placed on instantiations (which get broken up
111 -- into separate calls in Error_Msg). Span is the location on which the
112 -- flag will be placed in the output. In the case where the flag is on
113 -- the template, this points directly to the template, not to one of the
114 -- instantiation copies of the template. Opan is the original location
115 -- used to flag the error, and this may indeed point to an instantiation
116 -- copy. So typically we can see Opan pointing to the template location
117 -- in an instantiation copy when Span points to the source location of
118 -- the actual instantiation (i.e the line with the new). Msg_Cont is
119 -- set true if this is a continuation message. Node is the relevant
120 -- Node_Id for this message, to be used to compute the enclosing entity if
121 -- Opt.Include_Subprogram_In_Messages is set.
123 function No_Warnings (N : Node_Or_Entity_Id) return Boolean;
124 -- Determines if warnings should be suppressed for the given node
126 function OK_Node (N : Node_Id) return Boolean;
127 -- Determines if a node is an OK node to place an error message on (return
128 -- True) or if the error message should be suppressed (return False). A
129 -- message is suppressed if the node already has an error posted on it,
130 -- or if it refers to an Etype that has an error posted on it, or if
131 -- it references an Entity that has an error posted on it.
133 procedure Output_JSON_Message (Error_Id : Error_Msg_Id);
134 -- Output error message Error_Id and any subsequent continuation message
135 -- using a JSON format similar to the one GCC uses when passed
136 -- -fdiagnostics-format=json.
138 procedure Output_Source_Line
139 (L : Physical_Line_Number;
140 Sfile : Source_File_Index;
141 Errs : Boolean);
142 -- Outputs text of source line L, in file S, together with preceding line
143 -- number, as described above for Output_Line_Number. The Errs parameter
144 -- indicates if there are errors attached to the line, which forces
145 -- listing on, even in the presence of pragma List (Off).
147 procedure Set_Msg_Insertion_Column;
148 -- Handle column number insertion (@ insertion character)
150 procedure Set_Msg_Insertion_Node;
151 -- Handle node (name from node) insertion (& insertion character)
153 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr);
154 -- Handle type reference (right brace insertion character). Flag is the
155 -- location of the flag, which is provided for the internal call to
156 -- Set_Msg_Insertion_Line_Number,
158 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True);
159 -- Handle unit name insertion ($ insertion character). Depending on Boolean
160 -- parameter Suffix, (spec) or (body) is appended after the unit name.
162 procedure Set_Msg_Node (Node : Node_Id);
163 -- Add the sequence of characters for the name associated with the given
164 -- node to the current message. For N_Designator, N_Selected_Component,
165 -- N_Defining_Program_Unit_Name, and N_Expanded_Name, the Prefix is
166 -- included as well.
168 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr);
169 -- Add a sequence of characters to the current message. The characters may
170 -- be one of the special insertion characters (see documentation in spec).
171 -- Flag is the location at which the error is to be posted, which is used
172 -- to determine whether or not the # insertion needs a file name. The
173 -- variables Msg_Buffer are set on return Msglen.
175 procedure Set_Posted (N : Node_Id);
176 -- Sets the Error_Posted flag on the given node, and all its parents that
177 -- are subexpressions and then on the parent non-subexpression construct
178 -- that contains the original expression. If that parent is a named
179 -- association, the flag is further propagated to its parent. This is done
180 -- in order to guard against cascaded errors. Note that this call has an
181 -- effect for a serious error only.
183 procedure Set_Qualification (N : Nat; E : Entity_Id);
184 -- Outputs up to N levels of qualification for the given entity. For
185 -- example, the entity A.B.C.D will output B.C. if N = 2.
187 function Special_Msg_Delete
188 (Msg : String;
189 N : Node_Or_Entity_Id;
190 E : Node_Or_Entity_Id) return Boolean;
191 -- This function is called from Error_Msg_NEL, passing the message Msg,
192 -- node N on which the error is to be posted, and the entity or node E
193 -- to be used for an & insertion in the message if any. The job of this
194 -- procedure is to test for certain cascaded messages that we would like
195 -- to suppress. If the message is to be suppressed then we return True.
196 -- If the message should be generated (the normal case) False is returned.
198 procedure Unwind_Internal_Type (Ent : in out Entity_Id);
199 -- This procedure is given an entity id for an internal type, i.e. a type
200 -- with an internal name. It unwinds the type to try to get to something
201 -- reasonably printable, generating prefixes like "subtype of", "access
202 -- to", etc along the way in the buffer. The value in Ent on return is the
203 -- final name to be printed. Hopefully this is not an internal name, but in
204 -- some internal name cases, it is an internal name, and has to be printed
205 -- anyway (although in this case the message has been killed if possible).
206 -- The global variable Class_Flag is set to True if the resulting entity
207 -- should have 'Class appended to its name (see Add_Class procedure), and
208 -- is otherwise unchanged.
210 function Warn_Insertion return String;
211 -- This is called for warning messages only (so Warning_Msg_Char is set)
212 -- and returns a corresponding string to use at the beginning of generated
213 -- auxiliary messages, such as "in instantiation at ...".
214 -- "?" returns "??"
215 -- " " returns "?"
216 -- other trimmed, prefixed and suffixed with "?".
218 -----------------------
219 -- Change_Error_Text --
220 -----------------------
222 procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String) is
223 Save_Next : Error_Msg_Id;
224 Err_Id : Error_Msg_Id := Error_Id;
226 begin
227 Set_Msg_Text (New_Msg, Errors.Table (Error_Id).Sptr.Ptr);
228 Errors.Table (Error_Id).Text := new String'(Msg_Buffer (1 .. Msglen));
230 -- If in immediate error message mode, output modified error message now
231 -- This is just a bit tricky, because we want to output just a single
232 -- message, and the messages we modified is already linked in. We solve
233 -- this by temporarily resetting its forward pointer to empty.
235 if Debug_Flag_OO then
236 Save_Next := Errors.Table (Error_Id).Next;
237 Errors.Table (Error_Id).Next := No_Error_Msg;
238 Write_Eol;
239 Output_Source_Line
240 (Errors.Table (Error_Id).Line, Errors.Table (Error_Id).Sfile, True);
241 Output_Error_Msgs (Err_Id);
242 Errors.Table (Error_Id).Next := Save_Next;
243 end if;
244 end Change_Error_Text;
246 ------------------------
247 -- Compilation_Errors --
248 ------------------------
250 function Compilation_Errors return Boolean is
251 begin
252 if not Finalize_Called then
253 raise Program_Error;
255 -- Record that a compilation error was witnessed during a given phase of
256 -- analysis for gnat2why. This is needed as Warning_Mode is modified
257 -- twice in gnat2why, hence Erroutc.Compilation_Errors can only return a
258 -- suitable value for each phase of analysis separately.
260 else
261 Record_Compilation_Errors :=
262 Record_Compilation_Errors or else Erroutc.Compilation_Errors;
264 return Record_Compilation_Errors;
265 end if;
266 end Compilation_Errors;
268 --------------------------------------
269 -- Delete_Warning_And_Continuations --
270 --------------------------------------
272 procedure Delete_Warning_And_Continuations (Msg : Error_Msg_Id) is
273 Id : Error_Msg_Id;
275 begin
276 pragma Assert (not Errors.Table (Msg).Msg_Cont);
278 Id := Msg;
279 loop
280 declare
281 M : Error_Msg_Object renames Errors.Table (Id);
283 begin
284 if not M.Deleted then
285 M.Deleted := True;
286 Warnings_Detected := Warnings_Detected - 1;
288 if M.Info then
289 Warning_Info_Messages := Warning_Info_Messages - 1;
290 end if;
292 if M.Warn_Err then
293 Warnings_Treated_As_Errors := Warnings_Treated_As_Errors - 1;
294 end if;
295 end if;
297 Id := M.Next;
298 exit when Id = No_Error_Msg;
299 exit when not Errors.Table (Id).Msg_Cont;
300 end;
301 end loop;
302 end Delete_Warning_And_Continuations;
304 ---------------
305 -- Error_Msg --
306 ---------------
308 -- Error_Msg posts a flag at the given location, except that if the
309 -- Flag_Location/Flag_Span points within a generic template and corresponds
310 -- to an instantiation of this generic template, then the actual message
311 -- will be posted on the generic instantiation, along with additional
312 -- messages referencing the generic declaration.
314 procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
315 begin
316 Error_Msg (Msg, To_Span (Flag_Location), Current_Node);
317 end Error_Msg;
319 procedure Error_Msg (Msg : String; Flag_Span : Source_Span) is
320 begin
321 Error_Msg (Msg, Flag_Span, Current_Node);
322 end Error_Msg;
324 procedure Error_Msg
325 (Msg : String;
326 Flag_Location : Source_Ptr;
327 Is_Compile_Time_Pragma : Boolean)
329 Save_Is_Compile_Time_Msg : constant Boolean := Is_Compile_Time_Msg;
330 begin
331 Is_Compile_Time_Msg := Is_Compile_Time_Pragma;
332 Error_Msg (Msg, To_Span (Flag_Location), Current_Node);
333 Is_Compile_Time_Msg := Save_Is_Compile_Time_Msg;
334 end Error_Msg;
336 procedure Error_Msg
337 (Msg : String;
338 Flag_Location : Source_Ptr;
339 N : Node_Id)
341 begin
342 Error_Msg (Msg, To_Span (Flag_Location), N);
343 end Error_Msg;
345 procedure Error_Msg
346 (Msg : String;
347 Flag_Span : Source_Span;
348 N : Node_Id)
350 Flag_Location : constant Source_Ptr := Flag_Span.Ptr;
352 Sindex : Source_File_Index;
353 -- Source index for flag location
355 Orig_Loc : Source_Ptr;
356 -- Original location of Flag_Location (i.e. location in original
357 -- template in instantiation case, otherwise unchanged).
359 begin
360 -- Return if all errors are to be ignored
362 if Get_Ignore_Errors then
363 return;
364 end if;
366 -- If we already have messages, and we are trying to place a message at
367 -- No_Location, then just ignore the attempt since we assume that what
368 -- is happening is some cascaded junk. Note that this is safe in the
369 -- sense that proceeding will surely bomb. We will also bomb if the flag
370 -- location is No_Location and we don't have any messages so far, but
371 -- that is a real bug and a legitimate bomb, so we go ahead.
373 if Flag_Location = No_Location
374 and then Total_Errors_Detected > 0
375 then
376 return;
377 end if;
379 -- Start of processing for new message
381 Sindex := Get_Source_File_Index (Flag_Location);
382 Prescan_Message (Msg);
383 Orig_Loc := Original_Location (Flag_Location);
385 -- If the current location is in an instantiation, the issue arises of
386 -- whether to post the message on the template or the instantiation.
388 -- The way we decide is to see if we have posted the same message on
389 -- the template when we compiled the template (the template is always
390 -- compiled before any instantiations). For this purpose, we use a
391 -- separate table of messages. The reason we do this is twofold:
393 -- First, the messages can get changed by various processing
394 -- including the insertion of tokens etc, making it hard to
395 -- do the comparison.
397 -- Second, we will suppress a warning on a template if it is not in
398 -- the current extended source unit. That's reasonable and means we
399 -- don't want the warning on the instantiation here either, but it
400 -- does mean that the main error table would not in any case include
401 -- the message.
403 if Flag_Location = Orig_Loc then
404 Non_Instance_Msgs.Append ((new String'(Msg), Flag_Location));
405 Warn_On_Instance := False;
407 -- Here we have an instance message
409 else
410 -- Delete if debug flag off, and this message duplicates a message
411 -- already posted on the corresponding template
413 if not Debug_Flag_GG then
414 for J in Non_Instance_Msgs.First .. Non_Instance_Msgs.Last loop
415 if Msg = Non_Instance_Msgs.Table (J).Msg.all
416 and then Non_Instance_Msgs.Table (J).Loc = Orig_Loc
417 then
418 return;
419 end if;
420 end loop;
421 end if;
423 -- No duplicate, so error/warning will be posted on instance
425 Warn_On_Instance := Is_Warning_Msg;
426 end if;
428 -- Ignore warning message that is suppressed for this location. Note
429 -- that style checks are not considered warning messages for this
430 -- purpose.
432 if Is_Warning_Msg and then Warnings_Suppressed (Orig_Loc) /= No_String
433 then
434 return;
436 -- For style messages, check too many messages so far
438 elsif Is_Style_Msg
439 and then Maximum_Messages /= 0
440 and then Warnings_Detected >= Maximum_Messages
441 then
442 return;
444 -- Suppress warnings inside a loop that is known to be null or is
445 -- probably null (i.e. when loop executes only if invalid values
446 -- present). In either case warnings in the loop are likely to be junk.
448 elsif Is_Warning_Msg and then Present (N) then
450 declare
451 P : Node_Id;
453 begin
454 P := Parent (N);
455 while Present (P) loop
456 if Nkind (P) = N_Loop_Statement
457 and then Suppress_Loop_Warnings (P)
458 then
459 return;
460 end if;
462 P := Parent (P);
463 end loop;
464 end;
465 end if;
467 -- The idea at this stage is that we have two kinds of messages
469 -- First, we have those messages that are to be placed as requested at
470 -- Flag_Location. This includes messages that have nothing to do with
471 -- generics, and also messages placed on generic templates that reflect
472 -- an error in the template itself. For such messages we simply call
473 -- Error_Msg_Internal to place the message in the requested location.
475 if Instantiation (Sindex) = No_Location then
476 Error_Msg_Internal (Msg, Flag_Span, Flag_Span, False, N);
477 return;
478 end if;
480 -- If we are trying to flag an error in an instantiation, we may have
481 -- a generic contract violation. What we generate in this case is:
483 -- instantiation error at ...
484 -- original error message
486 -- or
488 -- warning: in instantiation at ...
489 -- warning: original warning message
491 -- or
493 -- info: in instantiation at ...
494 -- info: original info message
496 -- All these messages are posted at the location of the top level
497 -- instantiation. If there are nested instantiations, then the
498 -- instantiation error message can be repeated, pointing to each
499 -- of the relevant instantiations.
501 -- Note: the instantiation mechanism is also shared for inlining of
502 -- subprogram bodies when front end inlining is done. In this case the
503 -- messages have the form:
505 -- in inlined body at ...
506 -- original error message
508 -- or
510 -- warning: in inlined body at ...
511 -- warning: original warning message
513 -- or
515 -- info: in inlined body at ...
516 -- info: original info message
518 -- OK, here we have an instantiation error, and we need to generate the
519 -- error on the instantiation, rather than on the template.
521 declare
522 Actual_Error_Loc : Source_Ptr;
523 -- Location of outer level instantiation in instantiation case, or
524 -- just a copy of Flag_Location in the normal case. This is the
525 -- location where all error messages will actually be posted.
527 Save_Error_Msg_Sloc : constant Source_Ptr := Error_Msg_Sloc;
528 -- Save possible location set for caller's message. We need to use
529 -- Error_Msg_Sloc for the location of the instantiation error but we
530 -- have to preserve a possible original value.
532 X : Source_File_Index;
534 Msg_Cont_Status : Boolean;
535 -- Used to label continuation lines in instantiation case with
536 -- proper Msg_Cont status.
538 begin
539 -- Loop to find highest level instantiation, where all error
540 -- messages will be placed.
542 X := Sindex;
543 loop
544 Actual_Error_Loc := Instantiation (X);
545 X := Get_Source_File_Index (Actual_Error_Loc);
546 exit when Instantiation (X) = No_Location;
547 end loop;
549 -- Since we are generating the messages at the instantiation point in
550 -- any case, we do not want the references to the bad lines in the
551 -- instance to be annotated with the location of the instantiation.
553 Suppress_Instance_Location := True;
554 Msg_Cont_Status := False;
556 -- Loop to generate instantiation messages
558 Error_Msg_Sloc := Flag_Location;
559 X := Get_Source_File_Index (Flag_Location);
560 while Instantiation (X) /= No_Location loop
562 -- Suppress instantiation message on continuation lines
564 if Msg (Msg'First) /= '\' then
566 -- Case of inlined body
568 if Inlined_Body (X) then
569 if Is_Info_Msg then
570 Error_Msg_Internal
571 (Msg => "info: in inlined body #",
572 Span => To_Span (Actual_Error_Loc),
573 Opan => Flag_Span,
574 Msg_Cont => Msg_Cont_Status,
575 Node => N);
577 elsif Is_Warning_Msg then
578 Error_Msg_Internal
579 (Msg => Warn_Insertion & "in inlined body #",
580 Span => To_Span (Actual_Error_Loc),
581 Opan => Flag_Span,
582 Msg_Cont => Msg_Cont_Status,
583 Node => N);
585 elsif Is_Style_Msg then
586 Error_Msg_Internal
587 (Msg => "style: in inlined body #",
588 Span => To_Span (Actual_Error_Loc),
589 Opan => Flag_Span,
590 Msg_Cont => Msg_Cont_Status,
591 Node => N);
593 else
594 Error_Msg_Internal
595 (Msg => "error in inlined body #",
596 Span => To_Span (Actual_Error_Loc),
597 Opan => Flag_Span,
598 Msg_Cont => Msg_Cont_Status,
599 Node => N);
600 end if;
602 -- Case of generic instantiation
604 else
605 if Is_Info_Msg then
606 Error_Msg_Internal
607 (Msg => "info: in instantiation #",
608 Span => To_Span (Actual_Error_Loc),
609 Opan => Flag_Span,
610 Msg_Cont => Msg_Cont_Status,
611 Node => N);
613 elsif Is_Warning_Msg then
614 Error_Msg_Internal
615 (Msg => Warn_Insertion & "in instantiation #",
616 Span => To_Span (Actual_Error_Loc),
617 Opan => Flag_Span,
618 Msg_Cont => Msg_Cont_Status,
619 Node => N);
621 elsif Is_Style_Msg then
622 Error_Msg_Internal
623 (Msg => "style: in instantiation #",
624 Span => To_Span (Actual_Error_Loc),
625 Opan => Flag_Span,
626 Msg_Cont => Msg_Cont_Status,
627 Node => N);
629 else
630 Error_Msg_Internal
631 (Msg => "instantiation error #",
632 Span => To_Span (Actual_Error_Loc),
633 Opan => Flag_Span,
634 Msg_Cont => Msg_Cont_Status,
635 Node => N);
636 end if;
637 end if;
638 end if;
640 Error_Msg_Sloc := Instantiation (X);
641 X := Get_Source_File_Index (Error_Msg_Sloc);
642 Msg_Cont_Status := True;
643 end loop;
645 Suppress_Instance_Location := False;
646 Error_Msg_Sloc := Save_Error_Msg_Sloc;
648 -- Here we output the original message on the outer instantiation
650 Error_Msg_Internal
651 (Msg => Msg,
652 Span => To_Span (Actual_Error_Loc),
653 Opan => Flag_Span,
654 Msg_Cont => Msg_Cont_Status,
655 Node => N);
656 end;
657 end Error_Msg;
659 ----------------------------------
660 -- Error_Msg_Ada_2005_Extension --
661 ----------------------------------
663 procedure Error_Msg_Ada_2005_Extension (Extension : String) is
664 Loc : constant Source_Ptr := Token_Ptr;
665 begin
666 if Ada_Version < Ada_2005 then
667 Error_Msg (Extension & " is an Ada 2005 extension", Loc);
669 if No (Ada_Version_Pragma) then
670 Error_Msg ("\unit must be compiled with -gnat05 switch", Loc);
671 else
672 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
673 Error_Msg ("\incompatible with Ada version set#", Loc);
674 end if;
675 end if;
676 end Error_Msg_Ada_2005_Extension;
678 --------------------------------
679 -- Error_Msg_Ada_2012_Feature --
680 --------------------------------
682 procedure Error_Msg_Ada_2012_Feature (Feature : String; Loc : Source_Ptr) is
683 begin
684 if Ada_Version < Ada_2012 then
685 Error_Msg (Feature & " is an Ada 2012 feature", Loc);
687 if No (Ada_Version_Pragma) then
688 Error_Msg ("\unit must be compiled with -gnat2012 switch", Loc);
689 else
690 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
691 Error_Msg ("\incompatible with Ada version set#", Loc);
692 end if;
693 end if;
694 end Error_Msg_Ada_2012_Feature;
696 --------------------------------
697 -- Error_Msg_Ada_2022_Feature --
698 --------------------------------
700 procedure Error_Msg_Ada_2022_Feature (Feature : String; Loc : Source_Ptr) is
701 begin
702 if Ada_Version < Ada_2022 then
703 Error_Msg (Feature & " is an Ada 2022 feature", Loc);
705 if No (Ada_Version_Pragma) then
706 Error_Msg ("\unit must be compiled with -gnat2022 switch", Loc);
707 else
708 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
709 Error_Msg ("\incompatible with Ada version set#", Loc);
710 end if;
711 end if;
712 end Error_Msg_Ada_2022_Feature;
714 ------------------
715 -- Error_Msg_AP --
716 ------------------
718 procedure Error_Msg_AP (Msg : String) is
719 S1 : Source_Ptr;
720 C : Character;
722 begin
723 -- If we had saved the Scan_Ptr value after scanning the previous
724 -- token, then we would have exactly the right place for putting
725 -- the flag immediately at hand. However, that would add at least
726 -- two instructions to a Scan call *just* to service the possibility
727 -- of an Error_Msg_AP call. So instead we reconstruct that value.
729 -- We have two possibilities, start with Prev_Token_Ptr and skip over
730 -- the current token, which is made harder by the possibility that this
731 -- token may be in error, or start with Token_Ptr and work backwards.
732 -- We used to take the second approach, but it's hard because of
733 -- comments, and harder still because things that look like comments
734 -- can appear inside strings. So now we take the first approach.
736 -- Note: in the case where there is no previous token, Prev_Token_Ptr
737 -- is set to Source_First, which is a reasonable position for the
738 -- error flag in this situation.
740 S1 := Prev_Token_Ptr;
741 C := Source (S1);
743 -- If the previous token is a string literal, we need a special approach
744 -- since there may be white space inside the literal and we don't want
745 -- to stop on that white space.
747 -- Note: since this is an error recovery issue anyway, it is not worth
748 -- worrying about special UTF_32 line terminator characters here.
750 if Prev_Token = Tok_String_Literal then
751 loop
752 S1 := S1 + 1;
754 if Source (S1) = C then
755 S1 := S1 + 1;
756 exit when Source (S1) /= C;
757 elsif Source (S1) in Line_Terminator then
758 exit;
759 end if;
760 end loop;
762 -- Character literal also needs special handling
764 elsif Prev_Token = Tok_Char_Literal then
765 S1 := S1 + 3;
767 -- Otherwise we search forward for the end of the current token, marked
768 -- by a line terminator, white space, a comment symbol or if we bump
769 -- into the following token (i.e. the current token).
771 -- Again, it is not worth worrying about UTF_32 special line terminator
772 -- characters in this context, since this is only for error recovery.
774 else
775 while Source (S1) not in Line_Terminator
776 and then Source (S1) /= ' '
777 and then Source (S1) /= ASCII.HT
778 and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-')
779 and then S1 /= Token_Ptr
780 loop
781 S1 := S1 + 1;
782 end loop;
783 end if;
785 -- S1 is now set to the location for the flag
787 Error_Msg (Msg, S1);
788 end Error_Msg_AP;
790 ------------------
791 -- Error_Msg_BC --
792 ------------------
794 procedure Error_Msg_BC (Msg : String) is
795 begin
796 -- If we are at end of file, post the flag after the previous token
798 if Token = Tok_EOF then
799 Error_Msg_AP (Msg);
801 -- If we are at start of file, post the flag at the current token
803 elsif Token_Ptr = Source_First (Current_Source_File) then
804 Error_Msg_SC (Msg);
806 -- If the character before the current token is a space or a horizontal
807 -- tab, then we place the flag on this character (in the case of a tab
808 -- we would really like to place it in the "last" character of the tab
809 -- space, but that it too much trouble to worry about).
811 elsif Source (Token_Ptr - 1) = ' '
812 or else Source (Token_Ptr - 1) = ASCII.HT
813 then
814 Error_Msg (Msg, Token_Ptr - 1);
816 -- If there is no space or tab before the current token, then there is
817 -- no room to place the flag before the token, so we place it on the
818 -- token instead (this happens for example at the start of a line).
820 else
821 Error_Msg (Msg, Token_Ptr);
822 end if;
823 end Error_Msg_BC;
825 -------------------
826 -- Error_Msg_CRT --
827 -------------------
829 procedure Error_Msg_CRT (Feature : String; N : Node_Id) is
830 begin
831 if No_Run_Time_Mode then
832 Error_Msg_N ('|' & Feature & " not allowed in no run time mode", N);
834 else pragma Assert (Configurable_Run_Time_Mode);
835 Error_Msg_N ('|' & Feature & " not supported by configuration>", N);
836 end if;
838 Configurable_Run_Time_Violations := Configurable_Run_Time_Violations + 1;
839 end Error_Msg_CRT;
841 ------------------
842 -- Error_Msg_PT --
843 ------------------
845 procedure Error_Msg_PT (E : Entity_Id; Iface_Prim : Entity_Id) is
846 begin
847 Error_Msg_N
848 ("illegal overriding of subprogram inherited from interface", E);
850 Error_Msg_Sloc := Sloc (Iface_Prim);
852 if Ekind (E) = E_Function then
853 Error_Msg_N
854 ("\first formal of & declared # must be of mode `IN` "
855 & "or access-to-constant", E);
856 else
857 Error_Msg_N
858 ("\first formal of & declared # must be of mode `OUT`, `IN OUT` "
859 & "or access-to-variable", E);
860 end if;
861 end Error_Msg_PT;
863 -----------------
864 -- Error_Msg_F --
865 -----------------
867 procedure Error_Msg_F (Msg : String; N : Node_Id) is
868 Fst, Lst : Node_Id;
869 begin
870 First_And_Last_Nodes (N, Fst, Lst);
871 Error_Msg_NEL (Msg, N, N,
872 To_Span (Ptr => Sloc (Fst),
873 First => First_Sloc (Fst),
874 Last => Last_Sloc (Lst)));
875 end Error_Msg_F;
877 ------------------
878 -- Error_Msg_FE --
879 ------------------
881 procedure Error_Msg_FE
882 (Msg : String;
883 N : Node_Id;
884 E : Node_Or_Entity_Id)
886 Fst, Lst : Node_Id;
887 begin
888 First_And_Last_Nodes (N, Fst, Lst);
889 Error_Msg_NEL (Msg, N, E,
890 To_Span (Ptr => Sloc (Fst),
891 First => First_Sloc (Fst),
892 Last => Last_Sloc (Lst)));
893 end Error_Msg_FE;
895 ------------------------------
896 -- Error_Msg_GNAT_Extension --
897 ------------------------------
899 procedure Error_Msg_GNAT_Extension (Extension : String; Loc : Source_Ptr) is
900 begin
901 if not Extensions_Allowed then
902 Error_Msg (Extension & " is a 'G'N'A'T-specific extension", Loc);
904 if No (Ada_Version_Pragma) then
905 Error_Msg ("\unit must be compiled with -gnatX "
906 & "or use pragma Extensions_Allowed (On)", Loc);
907 else
908 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
909 Error_Msg ("\incompatible with Ada version set#", Loc);
910 Error_Msg ("\must use pragma Extensions_Allowed (On)", Loc);
911 end if;
912 end if;
913 end Error_Msg_GNAT_Extension;
915 ------------------------
916 -- Error_Msg_Internal --
917 ------------------------
919 procedure Error_Msg_Internal
920 (Msg : String;
921 Span : Source_Span;
922 Opan : Source_Span;
923 Msg_Cont : Boolean;
924 Node : Node_Id)
926 Sptr : constant Source_Ptr := Span.Ptr;
927 Optr : constant Source_Ptr := Opan.Ptr;
929 Next_Msg : Error_Msg_Id;
930 -- Pointer to next message at insertion point
932 Prev_Msg : Error_Msg_Id;
933 -- Pointer to previous message at insertion point
935 Temp_Msg : Error_Msg_Id;
937 Warn_Err : Boolean;
938 -- Set if warning to be treated as error
940 procedure Handle_Serious_Error;
941 -- Internal procedure to do all error message handling for a serious
942 -- error message, other than bumping the error counts and arranging
943 -- for the message to be output.
945 --------------------------
946 -- Handle_Serious_Error --
947 --------------------------
949 procedure Handle_Serious_Error is
950 begin
951 -- Turn off code generation if not done already
953 if Operating_Mode = Generate_Code then
954 Operating_Mode := Check_Semantics;
955 Expander_Active := False;
956 end if;
958 -- Set the fatal error flag in the unit table unless we are in
959 -- Try_Semantics mode (in which case we set ignored mode if not
960 -- currently set. This stops the semantics from being performed
961 -- if we find a serious error. This is skipped if we are currently
962 -- dealing with the configuration pragma file.
964 if Current_Source_Unit /= No_Unit then
965 declare
966 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
967 begin
968 if Try_Semantics then
969 if Fatal_Error (U) = None then
970 Set_Fatal_Error (U, Error_Ignored);
971 end if;
972 else
973 Set_Fatal_Error (U, Error_Detected);
974 end if;
975 end;
976 end if;
978 -- Disable warnings on unused use clauses and the like. Otherwise, an
979 -- error might hide a reference to an entity in a used package, so
980 -- after fixing the error, the use clause no longer looks like it was
981 -- unused.
983 Check_Unreferenced := False;
984 Check_Unreferenced_Formals := False;
985 end Handle_Serious_Error;
987 -- Start of processing for Error_Msg_Internal
989 begin
990 -- Detect common mistake of prefixing or suffing the message with a
991 -- space character.
993 pragma Assert (Msg (Msg'First) /= ' ' and then Msg (Msg'Last) /= ' ');
995 if Raise_Exception_On_Error /= 0 then
996 raise Error_Msg_Exception;
997 end if;
999 Continuation := Msg_Cont;
1000 Continuation_New_Line := False;
1001 Suppress_Message := False;
1002 Kill_Message := False;
1003 Set_Msg_Text (Msg, Sptr);
1005 -- Kill continuation if parent message killed
1007 if Continuation and Last_Killed then
1008 return;
1009 end if;
1011 -- Return without doing anything if message is suppressed
1013 if Suppress_Message
1014 and then not All_Errors_Mode
1015 and then not Is_Warning_Msg
1016 and then not Is_Unconditional_Msg
1017 then
1018 if not Continuation then
1019 Last_Killed := True;
1020 end if;
1022 return;
1023 end if;
1025 -- Return without doing anything if message is killed and this is not
1026 -- the first error message. The philosophy is that if we get a weird
1027 -- error message and we already have had a message, then we hope the
1028 -- weird message is a junk cascaded message
1030 if Kill_Message
1031 and then not All_Errors_Mode
1032 and then Total_Errors_Detected /= 0
1033 then
1034 if not Continuation then
1035 Last_Killed := True;
1036 end if;
1038 return;
1039 end if;
1041 -- Special check for warning message to see if it should be output
1043 if Is_Warning_Msg then
1045 -- Immediate return if warning message and warnings are suppressed
1047 if Warnings_Suppressed (Optr) /= No_String
1048 or else
1049 Warnings_Suppressed (Sptr) /= No_String
1050 then
1051 Cur_Msg := No_Error_Msg;
1052 return;
1053 end if;
1055 -- If the flag location is in the main extended source unit then for
1056 -- sure we want the warning since it definitely belongs
1058 if In_Extended_Main_Source_Unit (Sptr) then
1059 null;
1061 -- If the main unit has not been read yet. The warning must be on
1062 -- a configuration file: gnat.adc or user-defined. This means we
1063 -- are not parsing the main unit yet, so skip following checks.
1065 elsif No (Cunit (Main_Unit)) then
1066 null;
1068 -- If the flag location is not in the extended main source unit, then
1069 -- we want to eliminate the warning, unless it is in the extended
1070 -- main code unit and we want warnings on the instance.
1072 elsif In_Extended_Main_Code_Unit (Sptr) and then Warn_On_Instance then
1073 null;
1075 -- Keep warning if debug flag G set
1077 elsif Debug_Flag_GG then
1078 null;
1080 -- Keep warning if message text contains !!
1082 elsif Has_Double_Exclam then
1083 null;
1085 -- Here is where we delete a warning from a with'ed unit
1087 else
1088 Cur_Msg := No_Error_Msg;
1090 if not Continuation then
1091 Last_Killed := True;
1092 end if;
1094 return;
1095 end if;
1096 end if;
1098 -- If message is to be ignored in special ignore message mode, this is
1099 -- where we do this special processing, bypassing message output.
1101 if Ignore_Errors_Enable > 0 then
1102 if Is_Serious_Error then
1103 Handle_Serious_Error;
1104 end if;
1106 return;
1107 end if;
1109 -- If error message line length set, and this is a continuation message
1110 -- then all we do is to append the text to the text of the last message
1111 -- with a comma space separator (eliminating a possible (style) or
1112 -- info prefix).
1114 if Error_Msg_Line_Length /= 0 and then Continuation then
1115 Cur_Msg := Errors.Last;
1117 declare
1118 Oldm : String_Ptr := Errors.Table (Cur_Msg).Text;
1119 Newm : String (1 .. Oldm'Last + 2 + Msglen);
1120 Newl : Natural;
1121 M : Natural;
1123 begin
1124 -- First copy old message to new one and free it
1126 Newm (Oldm'Range) := Oldm.all;
1127 Newl := Oldm'Length;
1128 Free (Oldm);
1130 -- Remove (style) or info: at start of message
1132 if Msglen > 8 and then Msg_Buffer (1 .. 8) = "(style) " then
1133 M := 9;
1135 elsif Msglen > 6 and then Msg_Buffer (1 .. 6) = "info: " then
1136 M := 7;
1138 else
1139 M := 1;
1140 end if;
1142 -- Now deal with separation between messages. Normally this is
1143 -- simply comma space, but there are some special cases.
1145 -- If continuation new line, then put actual NL character in msg
1147 if Continuation_New_Line then
1148 Newl := Newl + 1;
1149 Newm (Newl) := ASCII.LF;
1151 -- If continuation message is enclosed in parentheses, then
1152 -- special treatment (don't need a comma, and we want to combine
1153 -- successive parenthetical remarks into a single one with
1154 -- separating commas).
1156 elsif Msg_Buffer (M) = '(' and then Msg_Buffer (Msglen) = ')' then
1158 -- Case where existing message ends in right paren, remove
1159 -- and separate parenthetical remarks with a comma.
1161 if Newm (Newl) = ')' then
1162 Newm (Newl) := ',';
1163 Msg_Buffer (M) := ' ';
1165 -- Case where we are adding new parenthetical comment
1167 else
1168 Newl := Newl + 1;
1169 Newm (Newl) := ' ';
1170 end if;
1172 -- Case where continuation not in parens and no new line
1174 else
1175 Newm (Newl + 1 .. Newl + 2) := ", ";
1176 Newl := Newl + 2;
1177 end if;
1179 -- Append new message
1181 Newm (Newl + 1 .. Newl + Msglen - M + 1) :=
1182 Msg_Buffer (M .. Msglen);
1183 Newl := Newl + Msglen - M + 1;
1184 Errors.Table (Cur_Msg).Text := new String'(Newm (1 .. Newl));
1186 -- Update warning msg flag and message doc char if needed
1188 if Is_Warning_Msg then
1189 if not Errors.Table (Cur_Msg).Warn then
1190 Errors.Table (Cur_Msg).Warn := True;
1191 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1193 elsif Warning_Msg_Char /= " " then
1194 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1195 end if;
1196 end if;
1197 end;
1199 return;
1200 end if;
1202 -- Here we build a new error object
1204 Errors.Append
1205 ((Text => new String'(Msg_Buffer (1 .. Msglen)),
1206 Next => No_Error_Msg,
1207 Prev => No_Error_Msg,
1208 Sptr => Span,
1209 Optr => Optr,
1210 Insertion_Sloc => (if Has_Insertion_Line then Error_Msg_Sloc
1211 else No_Location),
1212 Sfile => Get_Source_File_Index (Sptr),
1213 Line => Get_Physical_Line_Number (Sptr),
1214 Col => Get_Column_Number (Sptr),
1215 Compile_Time_Pragma => Is_Compile_Time_Msg,
1216 Warn => Is_Warning_Msg,
1217 Info => Is_Info_Msg,
1218 Check => Is_Check_Msg,
1219 Warn_Err => False, -- reset below
1220 Warn_Chr => Warning_Msg_Char,
1221 Warn_Runtime_Raise => Is_Runtime_Raise,
1222 Style => Is_Style_Msg,
1223 Serious => Is_Serious_Error,
1224 Uncond => Is_Unconditional_Msg,
1225 Msg_Cont => Continuation,
1226 Deleted => False,
1227 Node => Node));
1228 Cur_Msg := Errors.Last;
1230 -- Test if warning to be treated as error
1232 Warn_Err :=
1233 (Is_Warning_Msg or Is_Style_Msg)
1234 and then (Warning_Treated_As_Error (Msg_Buffer (1 .. Msglen))
1235 or else
1236 Warning_Treated_As_Error (Get_Warning_Tag (Cur_Msg)));
1238 -- Propagate Warn_Err to this message and preceding continuations.
1239 -- Likewise, propagate Is_Warning_Msg and Is_Runtime_Raise, because the
1240 -- current continued message could have been escalated from warning to
1241 -- error.
1243 for J in reverse 1 .. Errors.Last loop
1244 Errors.Table (J).Warn_Err := Warn_Err;
1245 Errors.Table (J).Warn := Is_Warning_Msg;
1246 Errors.Table (J).Warn_Runtime_Raise := Is_Runtime_Raise;
1247 exit when not Errors.Table (J).Msg_Cont;
1248 end loop;
1250 -- If immediate errors mode set, output error message now. Also output
1251 -- now if the -d1 debug flag is set (so node number message comes out
1252 -- just before actual error message)
1254 if Debug_Flag_OO or else Debug_Flag_1 then
1255 Write_Eol;
1256 Output_Source_Line
1257 (Errors.Table (Cur_Msg).Line, Errors.Table (Cur_Msg).Sfile, True);
1258 Temp_Msg := Cur_Msg;
1259 Output_Error_Msgs (Temp_Msg);
1261 -- If not in immediate errors mode, then we insert the message in the
1262 -- error chain for later output by Finalize. The messages are sorted
1263 -- first by unit (main unit comes first), and within a unit by source
1264 -- location (earlier flag location first in the chain).
1266 else
1267 -- First a quick check, does this belong at the very end of the chain
1268 -- of error messages. This saves a lot of time in the normal case if
1269 -- there are lots of messages.
1271 if Last_Error_Msg /= No_Error_Msg
1272 and then Errors.Table (Cur_Msg).Sfile =
1273 Errors.Table (Last_Error_Msg).Sfile
1274 and then (Sptr > Errors.Table (Last_Error_Msg).Sptr.Ptr
1275 or else
1276 (Sptr = Errors.Table (Last_Error_Msg).Sptr.Ptr
1277 and then
1278 Optr > Errors.Table (Last_Error_Msg).Optr))
1279 then
1280 Prev_Msg := Last_Error_Msg;
1281 Next_Msg := No_Error_Msg;
1283 -- Otherwise do a full sequential search for the insertion point
1285 else
1286 Prev_Msg := No_Error_Msg;
1287 Next_Msg := First_Error_Msg;
1288 while Next_Msg /= No_Error_Msg loop
1289 exit when
1290 Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
1292 if Errors.Table (Cur_Msg).Sfile = Errors.Table (Next_Msg).Sfile
1293 then
1294 exit when Sptr < Errors.Table (Next_Msg).Sptr.Ptr
1295 or else (Sptr = Errors.Table (Next_Msg).Sptr.Ptr
1296 and then Optr < Errors.Table (Next_Msg).Optr);
1297 end if;
1299 Prev_Msg := Next_Msg;
1300 Next_Msg := Errors.Table (Next_Msg).Next;
1301 end loop;
1302 end if;
1304 -- Now we insert the new message in the error chain.
1306 -- The possible insertion point for the new message is after Prev_Msg
1307 -- and before Next_Msg. However, this is where we do a special check
1308 -- for redundant parsing messages, defined as messages posted on the
1309 -- same line. The idea here is that probably such messages are junk
1310 -- from the parser recovering. In full errors mode, we don't do this
1311 -- deletion, but otherwise such messages are discarded at this stage.
1313 if Prev_Msg /= No_Error_Msg
1314 and then Errors.Table (Prev_Msg).Line =
1315 Errors.Table (Cur_Msg).Line
1316 and then Errors.Table (Prev_Msg).Sfile =
1317 Errors.Table (Cur_Msg).Sfile
1318 and then Compiler_State = Parsing
1319 and then not All_Errors_Mode
1320 then
1321 -- Don't delete unconditional messages and at this stage, don't
1322 -- delete continuation lines; we attempted to delete those earlier
1323 -- if the parent message was deleted.
1325 if not Errors.Table (Cur_Msg).Uncond
1326 and then not Continuation
1327 then
1328 -- Don't delete if prev msg is warning and new msg is an error.
1329 -- This is because we don't want a real error masked by a
1330 -- warning. In all other cases (that is parse errors for the
1331 -- same line that are not unconditional) we do delete the
1332 -- message. This helps to avoid junk extra messages from
1333 -- cascaded parsing errors
1335 if not (Errors.Table (Prev_Msg).Warn
1336 or else
1337 Errors.Table (Prev_Msg).Style)
1338 or else
1339 (Errors.Table (Cur_Msg).Warn
1340 or else
1341 Errors.Table (Cur_Msg).Style)
1342 then
1343 -- All tests passed, delete the message by simply returning
1344 -- without any further processing.
1346 pragma Assert (not Continuation);
1348 Last_Killed := True;
1349 return;
1350 end if;
1351 end if;
1352 end if;
1354 -- Come here if message is to be inserted in the error chain
1356 if not Continuation then
1357 Last_Killed := False;
1358 end if;
1360 if Prev_Msg = No_Error_Msg then
1361 First_Error_Msg := Cur_Msg;
1362 else
1363 Errors.Table (Prev_Msg).Next := Cur_Msg;
1364 end if;
1366 Errors.Table (Cur_Msg).Next := Next_Msg;
1368 if Next_Msg = No_Error_Msg then
1369 Last_Error_Msg := Cur_Msg;
1370 end if;
1371 end if;
1373 -- Bump appropriate statistics counts
1375 if Errors.Table (Cur_Msg).Info then
1377 -- Could be (usually is) both "info" and "warning"
1379 if Errors.Table (Cur_Msg).Warn then
1380 Warning_Info_Messages := Warning_Info_Messages + 1;
1381 Warnings_Detected := Warnings_Detected + 1;
1382 else
1383 Report_Info_Messages := Report_Info_Messages + 1;
1384 end if;
1386 elsif Errors.Table (Cur_Msg).Warn
1387 or else Errors.Table (Cur_Msg).Style
1388 then
1389 Warnings_Detected := Warnings_Detected + 1;
1391 elsif Errors.Table (Cur_Msg).Check then
1392 Check_Messages := Check_Messages + 1;
1394 else
1395 Total_Errors_Detected := Total_Errors_Detected + 1;
1397 if Errors.Table (Cur_Msg).Serious then
1398 Serious_Errors_Detected := Serious_Errors_Detected + 1;
1399 Handle_Serious_Error;
1401 -- If not serious error, set Fatal_Error to indicate ignored error
1403 else
1404 declare
1405 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
1406 begin
1407 if Fatal_Error (U) = None then
1408 Set_Fatal_Error (U, Error_Ignored);
1409 end if;
1410 end;
1411 end if;
1412 end if;
1414 -- Record warning message issued
1416 if Errors.Table (Cur_Msg).Warn
1417 and then not Errors.Table (Cur_Msg).Msg_Cont
1418 then
1419 Warning_Msg := Cur_Msg;
1420 end if;
1422 -- If too many warnings turn off warnings
1424 if Maximum_Messages /= 0 then
1425 if Warnings_Detected = Maximum_Messages then
1426 Warning_Mode := Suppress;
1427 end if;
1429 -- If too many errors abandon compilation
1431 if Total_Errors_Detected = Maximum_Messages then
1432 raise Unrecoverable_Error;
1433 end if;
1434 end if;
1435 end Error_Msg_Internal;
1437 -----------------
1438 -- Error_Msg_N --
1439 -----------------
1441 procedure Error_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
1442 Fst, Lst : Node_Id;
1443 begin
1444 First_And_Last_Nodes (N, Fst, Lst);
1445 Error_Msg_NEL (Msg, N, N,
1446 To_Span (Ptr => Sloc (N),
1447 First => First_Sloc (Fst),
1448 Last => Last_Sloc (Lst)));
1449 end Error_Msg_N;
1451 ------------------
1452 -- Error_Msg_NE --
1453 ------------------
1455 procedure Error_Msg_NE
1456 (Msg : String;
1457 N : Node_Or_Entity_Id;
1458 E : Node_Or_Entity_Id)
1460 Fst, Lst : Node_Id;
1461 begin
1462 First_And_Last_Nodes (N, Fst, Lst);
1463 Error_Msg_NEL (Msg, N, E,
1464 To_Span (Ptr => Sloc (N),
1465 First => First_Sloc (Fst),
1466 Last => Last_Sloc (Lst)));
1467 end Error_Msg_NE;
1469 -------------------
1470 -- Error_Msg_NEL --
1471 -------------------
1473 procedure Error_Msg_NEL
1474 (Msg : String;
1475 N : Node_Or_Entity_Id;
1476 E : Node_Or_Entity_Id;
1477 Flag_Location : Source_Ptr)
1479 Fst, Lst : Node_Id;
1480 begin
1481 First_And_Last_Nodes (N, Fst, Lst);
1482 Error_Msg_NEL
1483 (Msg, N, E,
1484 To_Span (Ptr => Flag_Location,
1485 First => Source_Ptr'Min (Flag_Location, First_Sloc (Fst)),
1486 Last => Source_Ptr'Max (Flag_Location, Last_Sloc (Lst))));
1487 end Error_Msg_NEL;
1489 procedure Error_Msg_NEL
1490 (Msg : String;
1491 N : Node_Or_Entity_Id;
1492 E : Node_Or_Entity_Id;
1493 Flag_Span : Source_Span)
1495 begin
1496 if Special_Msg_Delete (Msg, N, E) then
1497 return;
1498 end if;
1500 Prescan_Message (Msg);
1502 -- Special handling for warning messages
1504 if Is_Warning_Msg then
1506 -- Suppress if no warnings set for either entity or node
1508 if No_Warnings (N) or else No_Warnings (E) then
1510 -- Disable any continuation messages as well
1512 Last_Killed := True;
1513 return;
1514 end if;
1515 end if;
1517 -- Test for message to be output
1519 if All_Errors_Mode
1520 or else Is_Unconditional_Msg
1521 or else Is_Warning_Msg
1522 or else OK_Node (N)
1523 or else (Msg (Msg'First) = '\' and then not Last_Killed)
1524 then
1525 Debug_Output (N);
1526 Error_Msg_Node_1 := E;
1527 Error_Msg (Msg, Flag_Span, N);
1529 else
1530 Last_Killed := True;
1531 end if;
1533 if not Get_Ignore_Errors then
1534 Set_Posted (N);
1535 end if;
1536 end Error_Msg_NEL;
1538 ------------------
1539 -- Error_Msg_NW --
1540 ------------------
1542 procedure Error_Msg_NW
1543 (Eflag : Boolean;
1544 Msg : String;
1545 N : Node_Or_Entity_Id)
1547 Fst, Lst : Node_Id;
1548 begin
1549 if Eflag
1550 and then In_Extended_Main_Source_Unit (N)
1551 and then Comes_From_Source (N)
1552 then
1553 First_And_Last_Nodes (N, Fst, Lst);
1554 Error_Msg_NEL (Msg, N, N,
1555 To_Span (Ptr => Sloc (N),
1556 First => First_Sloc (Fst),
1557 Last => Last_Sloc (Lst)));
1558 end if;
1559 end Error_Msg_NW;
1561 -----------------
1562 -- Error_Msg_S --
1563 -----------------
1565 procedure Error_Msg_S (Msg : String) is
1566 begin
1567 Error_Msg (Msg, Scan_Ptr);
1568 end Error_Msg_S;
1570 ------------------
1571 -- Error_Msg_SC --
1572 ------------------
1574 procedure Error_Msg_SC (Msg : String) is
1575 begin
1576 -- If we are at end of file, post the flag after the previous token
1578 if Token = Tok_EOF then
1579 Error_Msg_AP (Msg);
1581 -- For all other cases the message is posted at the current token
1582 -- pointer position
1584 else
1585 Error_Msg (Msg, Token_Ptr);
1586 end if;
1587 end Error_Msg_SC;
1589 ------------------
1590 -- Error_Msg_SP --
1591 ------------------
1593 procedure Error_Msg_SP (Msg : String) is
1594 begin
1595 -- Note: in the case where there is no previous token, Prev_Token_Ptr
1596 -- is set to Source_First, which is a reasonable position for the
1597 -- error flag in this situation
1599 Error_Msg (Msg, Prev_Token_Ptr);
1600 end Error_Msg_SP;
1602 --------------
1603 -- Finalize --
1604 --------------
1606 procedure Finalize (Last_Call : Boolean) is
1607 Cur : Error_Msg_Id;
1608 Nxt : Error_Msg_Id;
1609 F : Error_Msg_Id;
1611 procedure Delete_Warning (E : Error_Msg_Id);
1612 -- Delete a warning msg if not already deleted and adjust warning count
1614 --------------------
1615 -- Delete_Warning --
1616 --------------------
1618 procedure Delete_Warning (E : Error_Msg_Id) is
1619 begin
1620 if not Errors.Table (E).Deleted then
1621 Errors.Table (E).Deleted := True;
1622 Warnings_Detected := Warnings_Detected - 1;
1624 if Errors.Table (E).Info then
1625 Warning_Info_Messages := Warning_Info_Messages - 1;
1626 end if;
1627 end if;
1628 end Delete_Warning;
1630 -- Start of processing for Finalize
1632 begin
1633 -- Set Prev pointers
1635 Cur := First_Error_Msg;
1636 while Cur /= No_Error_Msg loop
1637 Nxt := Errors.Table (Cur).Next;
1638 exit when Nxt = No_Error_Msg;
1639 Errors.Table (Nxt).Prev := Cur;
1640 Cur := Nxt;
1641 end loop;
1643 -- Eliminate any duplicated error messages from the list. This is
1644 -- done after the fact to avoid problems with Change_Error_Text.
1646 Cur := First_Error_Msg;
1647 while Cur /= No_Error_Msg loop
1648 Nxt := Errors.Table (Cur).Next;
1650 F := Nxt;
1651 while F /= No_Error_Msg
1652 and then Errors.Table (F).Sptr.Ptr = Errors.Table (Cur).Sptr.Ptr
1653 loop
1654 Check_Duplicate_Message (Cur, F);
1655 F := Errors.Table (F).Next;
1656 end loop;
1658 Cur := Nxt;
1659 end loop;
1661 -- Mark any messages suppressed by specific warnings as Deleted
1663 Cur := First_Error_Msg;
1664 while Cur /= No_Error_Msg loop
1665 declare
1666 CE : Error_Msg_Object renames Errors.Table (Cur);
1667 Tag : constant String := Get_Warning_Tag (Cur);
1669 begin
1670 if (CE.Warn and not CE.Deleted)
1671 and then
1672 (Warning_Specifically_Suppressed (CE.Sptr.Ptr, CE.Text, Tag)
1673 /= No_String
1674 or else
1675 Warning_Specifically_Suppressed (CE.Optr, CE.Text, Tag) /=
1676 No_String)
1677 then
1678 Delete_Warning (Cur);
1680 -- If this is a continuation, delete previous parts of message
1682 F := Cur;
1683 while Errors.Table (F).Msg_Cont loop
1684 F := Errors.Table (F).Prev;
1685 exit when F = No_Error_Msg;
1686 Delete_Warning (F);
1687 end loop;
1689 -- Delete any following continuations
1691 F := Cur;
1692 loop
1693 F := Errors.Table (F).Next;
1694 exit when F = No_Error_Msg;
1695 exit when not Errors.Table (F).Msg_Cont;
1696 Delete_Warning (F);
1697 end loop;
1698 end if;
1699 end;
1701 Cur := Errors.Table (Cur).Next;
1702 end loop;
1704 Finalize_Called := True;
1706 -- Check consistency of specific warnings (may add warnings). We only
1707 -- do this on the last call, after all possible warnings are posted.
1709 if Last_Call then
1710 Validate_Specific_Warnings (Error_Msg'Access);
1711 end if;
1712 end Finalize;
1714 ----------------
1715 -- First_Node --
1716 ----------------
1718 function First_Node (C : Node_Id) return Node_Id is
1719 Fst, Lst : Node_Id;
1720 begin
1721 First_And_Last_Nodes (C, Fst, Lst);
1722 return Fst;
1723 end First_Node;
1725 --------------------------
1726 -- First_And_Last_Nodes --
1727 --------------------------
1729 procedure First_And_Last_Nodes
1730 (C : Node_Id;
1731 First_Node, Last_Node : out Node_Id)
1733 Orig : constant Node_Id := Original_Node (C);
1734 Loc : constant Source_Ptr := Sloc (Orig);
1735 Sfile : constant Source_File_Index := Get_Source_File_Index (Loc);
1736 Earliest : Node_Id;
1737 Latest : Node_Id;
1738 Eloc : Source_Ptr;
1739 Lloc : Source_Ptr;
1741 function Test_First_And_Last (N : Node_Id) return Traverse_Result;
1742 -- Function applied to every node in the construct
1744 procedure Search_Tree_First_And_Last is new
1745 Traverse_Proc (Test_First_And_Last);
1746 -- Create traversal procedure
1748 -------------------------
1749 -- Test_First_And_Last --
1750 -------------------------
1752 function Test_First_And_Last (N : Node_Id) return Traverse_Result is
1753 Norig : constant Node_Id := Original_Node (N);
1754 Loc : constant Source_Ptr := Sloc (Norig);
1756 begin
1757 -- Check for earlier
1759 if Loc < Eloc
1761 -- Ignore nodes with no useful location information
1763 and then Loc /= Standard_Location
1764 and then Loc /= No_Location
1766 -- Ignore nodes from a different file. This ensures against cases
1767 -- of strange foreign code somehow being present. We don't want
1768 -- wild placement of messages if that happens.
1770 and then Get_Source_File_Index (Loc) = Sfile
1771 then
1772 Earliest := Norig;
1773 Eloc := Loc;
1774 end if;
1776 -- Check for later
1778 if Loc > Lloc
1780 -- Ignore nodes with no useful location information
1782 and then Loc /= Standard_Location
1783 and then Loc /= No_Location
1785 -- Ignore nodes from a different file. This ensures against cases
1786 -- of strange foreign code somehow being present. We don't want
1787 -- wild placement of messages if that happens.
1789 and then Get_Source_File_Index (Loc) = Sfile
1790 then
1791 Latest := Norig;
1792 Lloc := Loc;
1793 end if;
1795 return OK_Orig;
1796 end Test_First_And_Last;
1798 -- Start of processing for First_And_Last_Nodes
1800 begin
1801 if Nkind (Orig) in N_Subexpr
1802 | N_Declaration
1803 | N_Access_To_Subprogram_Definition
1804 | N_Generic_Instantiation
1805 | N_Later_Decl_Item
1806 | N_Use_Package_Clause
1807 | N_Array_Type_Definition
1808 | N_Renaming_Declaration
1809 | N_Generic_Renaming_Declaration
1810 | N_Assignment_Statement
1811 | N_Raise_Statement
1812 | N_Simple_Return_Statement
1813 | N_Exit_Statement
1814 | N_Pragma
1815 | N_Use_Type_Clause
1816 | N_With_Clause
1817 | N_Attribute_Definition_Clause
1818 | N_Subtype_Indication
1819 then
1820 Earliest := Orig;
1821 Eloc := Loc;
1822 Latest := Orig;
1823 Lloc := Loc;
1824 Search_Tree_First_And_Last (Orig);
1825 First_Node := Earliest;
1826 Last_Node := Latest;
1828 else
1829 First_Node := Orig;
1830 Last_Node := Orig;
1831 end if;
1832 end First_And_Last_Nodes;
1834 ----------------
1835 -- First_Sloc --
1836 ----------------
1838 function First_Sloc (N : Node_Id) return Source_Ptr is
1839 SI : constant Source_File_Index := Source_Index (Get_Source_Unit (N));
1840 SF : constant Source_Ptr := Source_First (SI);
1841 SL : constant Source_Ptr := Source_Last (SI);
1842 F : Node_Id;
1843 S : Source_Ptr;
1845 begin
1846 F := First_Node (N);
1847 S := Sloc (F);
1849 if S not in SF .. SL then
1850 return S;
1851 end if;
1853 -- The following circuit is a bit subtle. When we have parenthesized
1854 -- expressions, then the Sloc will not record the location of the paren,
1855 -- but we would like to post the flag on the paren. So what we do is to
1856 -- crawl up the tree from the First_Node, adjusting the Sloc value for
1857 -- any parentheses we know are present. Yes, we know this circuit is not
1858 -- 100% reliable (e.g. because we don't record all possible paren level
1859 -- values), but this is only for an error message so it is good enough.
1861 Node_Loop : loop
1862 Paren_Loop : for J in 1 .. Paren_Count (F) loop
1864 -- We don't look more than 12 characters behind the current
1865 -- location, and in any case not past the front of the source.
1867 Search_Loop : for K in 1 .. 12 loop
1868 exit Search_Loop when S = SF;
1870 if Source_Text (SI) (S - 1) = '(' then
1871 S := S - 1;
1872 exit Search_Loop;
1874 elsif Source_Text (SI) (S - 1) <= ' ' then
1875 S := S - 1;
1877 else
1878 exit Search_Loop;
1879 end if;
1880 end loop Search_Loop;
1881 end loop Paren_Loop;
1883 exit Node_Loop when F = N;
1884 F := Parent (F);
1885 exit Node_Loop when Nkind (F) not in N_Subexpr;
1886 end loop Node_Loop;
1888 return S;
1889 end First_Sloc;
1891 -----------------------
1892 -- Get_Ignore_Errors --
1893 -----------------------
1895 function Get_Ignore_Errors return Boolean is
1896 begin
1897 return Errors_Must_Be_Ignored;
1898 end Get_Ignore_Errors;
1900 ----------------
1901 -- Initialize --
1902 ----------------
1904 procedure Initialize is
1905 begin
1906 Errors.Init;
1907 First_Error_Msg := No_Error_Msg;
1908 Last_Error_Msg := No_Error_Msg;
1909 Serious_Errors_Detected := 0;
1910 Total_Errors_Detected := 0;
1911 Cur_Msg := No_Error_Msg;
1912 List_Pragmas.Init;
1914 -- Reset counts for warnings
1916 Reset_Warnings;
1918 -- Initialize warnings tables
1920 Warnings.Init;
1921 Specific_Warnings.Init;
1922 end Initialize;
1924 -------------------------------
1925 -- Is_Size_Too_Small_Message --
1926 -------------------------------
1928 function Is_Size_Too_Small_Message (S : String) return Boolean is
1929 Size_For : constant String := "size for";
1930 pragma Assert (Size_Too_Small_Message (1 .. Size_For'Last) = Size_For);
1931 -- Assert that Size_Too_Small_Message starts with Size_For
1932 begin
1933 return S'Length >= Size_For'Length
1934 and then S (S'First .. S'First + Size_For'Length - 1) = Size_For;
1935 -- True if S starts with Size_For
1936 end Is_Size_Too_Small_Message;
1938 ---------------
1939 -- Last_Node --
1940 ---------------
1942 function Last_Node (C : Node_Id) return Node_Id is
1943 Fst, Lst : Node_Id;
1944 begin
1945 First_And_Last_Nodes (C, Fst, Lst);
1946 return Lst;
1947 end Last_Node;
1949 ---------------
1950 -- Last_Sloc --
1951 ---------------
1953 function Last_Sloc (N : Node_Id) return Source_Ptr is
1954 SI : constant Source_File_Index := Source_Index (Get_Source_Unit (N));
1955 SF : constant Source_Ptr := Source_First (SI);
1956 SL : constant Source_Ptr := Source_Last (SI);
1957 F : Node_Id;
1958 S : Source_Ptr;
1960 begin
1961 F := Last_Node (N);
1962 S := Sloc (F);
1964 if S not in SF .. SL then
1965 return S;
1966 end if;
1968 -- Skip past an identifier
1970 while S in SF .. SL - 1
1971 and then Source_Text (SI) (S + 1)
1973 '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' | '.' | '_'
1974 loop
1975 S := S + 1;
1976 end loop;
1978 -- The following circuit attempts at crawling up the tree from the
1979 -- Last_Node, adjusting the Sloc value for any parentheses we know
1980 -- are present, similarly to what is done in First_Sloc.
1982 Node_Loop : loop
1983 Paren_Loop : for J in 1 .. Paren_Count (F) loop
1985 -- We don't look more than 12 characters after the current
1986 -- location
1988 Search_Loop : for K in 1 .. 12 loop
1989 exit Node_Loop when S = SL;
1991 if Source_Text (SI) (S + 1) = ')' then
1992 S := S + 1;
1993 exit Search_Loop;
1995 elsif Source_Text (SI) (S + 1) <= ' ' then
1996 S := S + 1;
1998 else
1999 exit Search_Loop;
2000 end if;
2001 end loop Search_Loop;
2002 end loop Paren_Loop;
2004 exit Node_Loop when F = N;
2005 F := Parent (F);
2006 exit Node_Loop when Nkind (F) not in N_Subexpr;
2007 end loop Node_Loop;
2009 -- Remove any trailing space
2011 while S in SF + 1 .. SL
2012 and then Source_Text (SI) (S) = ' '
2013 loop
2014 S := S - 1;
2015 end loop;
2017 return S;
2018 end Last_Sloc;
2020 -----------------
2021 -- No_Warnings --
2022 -----------------
2024 function No_Warnings (N : Node_Or_Entity_Id) return Boolean is
2025 begin
2026 if Error_Posted (N) then
2027 return True;
2029 elsif Nkind (N) in N_Entity and then Has_Warnings_Off (N) then
2030 return True;
2032 elsif Is_Entity_Name (N)
2033 and then Present (Entity (N))
2034 and then Has_Warnings_Off (Entity (N))
2035 then
2036 return True;
2038 else
2039 return False;
2040 end if;
2041 end No_Warnings;
2043 -------------
2044 -- OK_Node --
2045 -------------
2047 function OK_Node (N : Node_Id) return Boolean is
2048 K : constant Node_Kind := Nkind (N);
2050 begin
2051 if Error_Posted (N) then
2052 return False;
2054 elsif K in N_Has_Etype
2055 and then Present (Etype (N))
2056 and then Error_Posted (Etype (N))
2057 then
2058 return False;
2060 elsif (K in N_Op
2061 or else K = N_Attribute_Reference
2062 or else K = N_Character_Literal
2063 or else K = N_Expanded_Name
2064 or else K = N_Identifier
2065 or else K = N_Operator_Symbol)
2066 and then Present (Entity (N))
2067 and then Error_Posted (Entity (N))
2068 then
2069 return False;
2070 else
2071 return True;
2072 end if;
2073 end OK_Node;
2075 -------------------------
2076 -- Output_JSON_Message --
2077 -------------------------
2079 procedure Output_JSON_Message (Error_Id : Error_Msg_Id) is
2081 function Is_Continuation (E : Error_Msg_Id) return Boolean;
2082 -- Return True if E is a continuation message.
2084 procedure Write_JSON_Escaped_String (Str : String_Ptr);
2085 -- Write each character of Str, taking care of preceding each quote and
2086 -- backslash with a backslash. Note that this escaping differs from what
2087 -- GCC does.
2089 -- Indeed, the JSON specification mandates encoding wide characters
2090 -- either as their direct UTF-8 representation or as their escaped
2091 -- UTF-16 surrogate pairs representation. GCC seems to prefer escaping -
2092 -- we choose to use the UTF-8 representation instead.
2094 procedure Write_JSON_Location (Sptr : Source_Ptr);
2095 -- Write Sptr as a JSON location, an object containing a file attribute,
2096 -- a line number and a column number.
2098 procedure Write_JSON_Span (Span : Source_Span);
2099 -- Write Span as a JSON span, an object containing a "caret" attribute
2100 -- whose value is the JSON location of Span.Ptr. If Span.First and
2101 -- Span.Last are different from Span.Ptr, they will be printed as JSON
2102 -- locations under the names "start" and "finish".
2104 -----------------------
2105 -- Is_Continuation --
2106 -----------------------
2108 function Is_Continuation (E : Error_Msg_Id) return Boolean is
2109 begin
2110 return E <= Last_Error_Msg and then Errors.Table (E).Msg_Cont;
2111 end Is_Continuation;
2113 -------------------------------
2114 -- Write_JSON_Escaped_String --
2115 -------------------------------
2117 procedure Write_JSON_Escaped_String (Str : String_Ptr) is
2118 begin
2119 for C of Str.all loop
2120 if C = '"' or else C = '\' then
2121 Write_Char ('\');
2122 end if;
2124 Write_Char (C);
2125 end loop;
2126 end Write_JSON_Escaped_String;
2128 -------------------------
2129 -- Write_JSON_Location --
2130 -------------------------
2132 procedure Write_JSON_Location (Sptr : Source_Ptr) is
2133 begin
2134 Write_Str ("{""file"":""");
2135 Write_Name (Full_Ref_Name (Get_Source_File_Index (Sptr)));
2136 Write_Str (""",""line"":");
2137 Write_Int (Pos (Get_Physical_Line_Number (Sptr)));
2138 Write_Str (", ""column"":");
2139 Write_Int (Nat (Get_Column_Number (Sptr)));
2140 Write_Str ("}");
2141 end Write_JSON_Location;
2143 ---------------------
2144 -- Write_JSON_Span --
2145 ---------------------
2147 procedure Write_JSON_Span (Span : Source_Span) is
2148 begin
2149 Write_Str ("{""caret"":");
2150 Write_JSON_Location (Span.Ptr);
2152 if Span.Ptr /= Span.First then
2153 Write_Str (",""start"":");
2154 Write_JSON_Location (Span.First);
2155 end if;
2157 if Span.Ptr /= Span.Last then
2158 Write_Str (",""finish"":");
2159 Write_JSON_Location (Span.Last);
2160 end if;
2162 Write_Str ("}");
2163 end Write_JSON_Span;
2165 -- Local Variables
2167 E : Error_Msg_Id := Error_Id;
2169 Print_Continuations : constant Boolean := not Is_Continuation (E);
2170 -- Do not print continuations messages as children of the current
2171 -- message if the current message is a continuation message.
2173 -- Start of processing for Output_JSON_Message
2175 begin
2177 -- Print message kind
2179 Write_Str ("{""kind"":");
2181 if Errors.Table (E).Warn and then not Errors.Table (E).Warn_Err then
2182 Write_Str ("""warning""");
2183 elsif Errors.Table (E).Info or else Errors.Table (E).Check then
2184 Write_Str ("""note""");
2185 else
2186 Write_Str ("""error""");
2187 end if;
2189 -- Print message location
2191 Write_Str (",""locations"":[");
2192 Write_JSON_Span (Errors.Table (E).Sptr);
2194 if Errors.Table (E).Optr /= Errors.Table (E).Sptr.Ptr then
2195 Write_Str (",{""caret"":");
2196 Write_JSON_Location (Errors.Table (E).Optr);
2197 Write_Str ("}");
2198 end if;
2200 -- Print message content
2202 Write_Str ("],""message"":""");
2203 Write_JSON_Escaped_String (Errors.Table (E).Text);
2204 Write_Str ("""");
2206 E := E + 1;
2208 if Print_Continuations and then Is_Continuation (E) then
2210 Write_Str (",""children"": [");
2211 Output_JSON_Message (E);
2212 E := E + 1;
2214 while Is_Continuation (E) loop
2215 Write_Str (", ");
2216 Output_JSON_Message (E);
2217 E := E + 1;
2218 end loop;
2220 Write_Str ("]");
2222 end if;
2224 Write_Str ("}");
2225 end Output_JSON_Message;
2227 ---------------------
2228 -- Output_Messages --
2229 ---------------------
2231 procedure Output_Messages is
2233 -- Local subprograms
2235 procedure Write_Error_Summary;
2236 -- Write error summary
2238 procedure Write_Header (Sfile : Source_File_Index);
2239 -- Write header line (compiling or checking given file)
2241 procedure Write_Max_Errors;
2242 -- Write message if max errors reached
2244 procedure Write_Source_Code_Lines
2245 (Span : Source_Span;
2246 SGR_Span : String);
2247 -- Write the source code line corresponding to Span, as follows when
2248 -- Span in on one line:
2250 -- line | actual code line here with Span somewhere
2251 -- | ~~~~~^~~~
2253 -- where the caret on the line points to location Span.Ptr, and the
2254 -- range Span.First..Span.Last is underlined.
2256 -- or when the span is over multiple lines:
2258 -- line | beginning of the Span on this line
2259 -- ... | ...
2260 -- line>| actual code line here with Span.Ptr somewhere
2261 -- ... | ...
2262 -- line | end of the Span on this line
2264 -- or when the span is a simple location, as follows:
2266 -- line | actual code line here with Span somewhere
2267 -- | ^ here
2269 -- where the caret on the line points to location Span.Ptr
2271 -- SGR_Span is the SGR string to start the section of code in the span,
2272 -- that should be closed with SGR_Reset.
2274 -------------------------
2275 -- Write_Error_Summary --
2276 -------------------------
2278 procedure Write_Error_Summary is
2279 begin
2280 -- Extra blank line if error messages or source listing were output
2282 if Total_Errors_Detected + Warnings_Detected > 0 or else Full_List
2283 then
2284 Write_Eol;
2285 end if;
2287 -- Message giving number of lines read and number of errors detected.
2288 -- This normally goes to Standard_Output. The exception is when brief
2289 -- mode is not set, verbose mode (or full list mode) is set, and
2290 -- there are errors. In this case we send the message to standard
2291 -- error to make sure that *something* appears on standard error
2292 -- in an error situation.
2294 if Total_Errors_Detected + Warnings_Detected /= 0
2295 and then not Brief_Output
2296 and then (Verbose_Mode or Full_List)
2297 then
2298 Set_Standard_Error;
2299 end if;
2301 -- Message giving total number of lines. Don't give this message if
2302 -- the Main_Source line is unknown (this happens in error situations,
2303 -- e.g. when integrated preprocessing fails).
2305 if Main_Source_File > No_Source_File then
2306 Write_Str (" ");
2307 Write_Int (Num_Source_Lines (Main_Source_File));
2309 if Num_Source_Lines (Main_Source_File) = 1 then
2310 Write_Str (" line: ");
2311 else
2312 Write_Str (" lines: ");
2313 end if;
2314 end if;
2316 if Total_Errors_Detected = 0 then
2317 Write_Str ("No errors");
2319 elsif Total_Errors_Detected = 1 then
2320 Write_Str ("1 error");
2322 else
2323 Write_Int (Total_Errors_Detected);
2324 Write_Str (" errors");
2325 end if;
2327 -- We now need to output warnings. When using -gnatwe, all warnings
2328 -- should be treated as errors, except for warnings originating from
2329 -- the use of the Compile_Time_Warning pragma. Another situation
2330 -- where a warning might be treated as an error is when the source
2331 -- code contains a Warning_As_Error pragma.
2332 -- When warnings are treated as errors, we still log them as
2333 -- warnings, but we add a message denoting how many of these warnings
2334 -- are also errors.
2336 declare
2337 Warnings_Count : constant Int :=
2338 Warnings_Detected - Warning_Info_Messages;
2340 Compile_Time_Warnings : Int;
2341 -- Number of warnings that come from a Compile_Time_Warning
2342 -- pragma.
2344 Non_Compile_Time_Warnings : Int;
2345 -- Number of warnings that do not come from a Compile_Time_Warning
2346 -- pragmas.
2348 begin
2349 if Warnings_Count > 0 then
2350 Write_Str (", ");
2351 Write_Int (Warnings_Count);
2352 Write_Str (" warning");
2354 if Warnings_Count > 1 then
2355 Write_Char ('s');
2356 end if;
2358 Compile_Time_Warnings := Count_Compile_Time_Pragma_Warnings;
2359 Non_Compile_Time_Warnings :=
2360 Warnings_Count - Compile_Time_Warnings;
2362 if Warning_Mode = Treat_As_Error
2363 and then Non_Compile_Time_Warnings > 0
2364 then
2365 Write_Str (" (");
2367 if Compile_Time_Warnings > 0 then
2368 Write_Int (Non_Compile_Time_Warnings);
2369 Write_Str (" ");
2370 end if;
2372 Write_Str ("treated as error");
2374 if Non_Compile_Time_Warnings > 1 then
2375 Write_Char ('s');
2376 end if;
2378 Write_Char (')');
2380 elsif Warnings_Treated_As_Errors > 0 then
2381 Write_Str (" (");
2383 if Warnings_Treated_As_Errors /= Warnings_Count then
2384 Write_Int (Warnings_Treated_As_Errors);
2385 Write_Str (" ");
2386 end if;
2388 Write_Str ("treated as error");
2390 if Warnings_Treated_As_Errors > 1 then
2391 Write_Str ("s");
2392 end if;
2394 Write_Str (")");
2395 end if;
2396 end if;
2397 end;
2399 if Warning_Info_Messages + Report_Info_Messages /= 0 then
2400 Write_Str (", ");
2401 Write_Int (Warning_Info_Messages + Report_Info_Messages);
2402 Write_Str (" info message");
2404 if Warning_Info_Messages + Report_Info_Messages > 1 then
2405 Write_Char ('s');
2406 end if;
2407 end if;
2409 Write_Eol;
2410 Set_Standard_Output;
2411 end Write_Error_Summary;
2413 ------------------
2414 -- Write_Header --
2415 ------------------
2417 procedure Write_Header (Sfile : Source_File_Index) is
2418 begin
2419 if Verbose_Mode or Full_List then
2420 if Original_Operating_Mode = Generate_Code then
2421 Write_Str ("Compiling: ");
2422 else
2423 Write_Str ("Checking: ");
2424 end if;
2426 Write_Name (Full_File_Name (Sfile));
2428 if not Debug_Flag_7 then
2429 Write_Eol;
2430 Write_Str ("Source file time stamp: ");
2431 Write_Time_Stamp (Sfile);
2432 Write_Eol;
2433 Write_Str ("Compiled at: " & Compilation_Time);
2434 end if;
2436 Write_Eol;
2437 end if;
2438 end Write_Header;
2440 ----------------------
2441 -- Write_Max_Errors --
2442 ----------------------
2444 procedure Write_Max_Errors is
2445 begin
2446 if Maximum_Messages /= 0 then
2447 if Warnings_Detected >= Maximum_Messages then
2448 Set_Standard_Error;
2449 Write_Line ("maximum number of warnings output");
2450 Write_Line ("any further warnings suppressed");
2451 Set_Standard_Output;
2452 end if;
2454 -- If too many errors print message
2456 if Total_Errors_Detected >= Maximum_Messages then
2457 Set_Standard_Error;
2458 Write_Line ("fatal error: maximum number of errors detected");
2459 Set_Standard_Output;
2460 end if;
2461 end if;
2462 end Write_Max_Errors;
2464 -----------------------------
2465 -- Write_Source_Code_Lines --
2466 -----------------------------
2468 procedure Write_Source_Code_Lines
2469 (Span : Source_Span;
2470 SGR_Span : String)
2472 function Get_Line_End
2473 (Buf : Source_Buffer_Ptr;
2474 Loc : Source_Ptr) return Source_Ptr;
2475 -- Get the source location for the end of the line in Buf for Loc. If
2476 -- Loc is past the end of Buf already, return Buf'Last.
2478 function Get_Line_Start
2479 (Buf : Source_Buffer_Ptr;
2480 Loc : Source_Ptr) return Source_Ptr;
2481 -- Get the source location for the start of the line in Buf for Loc
2483 function Image (X : Positive; Width : Positive) return String;
2484 -- Output number X over Width characters, with whitespace padding.
2485 -- Only output the low-order Width digits of X, if X is larger than
2486 -- Width digits.
2488 procedure Write_Buffer
2489 (Buf : Source_Buffer_Ptr;
2490 First : Source_Ptr;
2491 Last : Source_Ptr);
2492 -- Output the characters from First to Last position in Buf, using
2493 -- Write_Buffer_Char.
2495 procedure Write_Buffer_Char
2496 (Buf : Source_Buffer_Ptr;
2497 Loc : Source_Ptr);
2498 -- Output the characters at position Loc in Buf, translating ASCII.HT
2499 -- in a suitable number of spaces so that the output is not modified
2500 -- by starting in a different column that 1.
2502 procedure Write_Line_Marker
2503 (Num : Pos;
2504 Mark : Boolean;
2505 Width : Positive);
2506 -- Output the line number Num over Width characters, with possibly
2507 -- a Mark to denote the line with the main location when reporting
2508 -- a span over multiple lines.
2510 ------------------
2511 -- Get_Line_End --
2512 ------------------
2514 function Get_Line_End
2515 (Buf : Source_Buffer_Ptr;
2516 Loc : Source_Ptr) return Source_Ptr
2518 Cur_Loc : Source_Ptr := Source_Ptr'Min (Loc, Buf'Last);
2519 begin
2520 while Cur_Loc < Buf'Last
2521 and then Buf (Cur_Loc) /= ASCII.LF
2522 loop
2523 Cur_Loc := Cur_Loc + 1;
2524 end loop;
2526 return Cur_Loc;
2527 end Get_Line_End;
2529 --------------------
2530 -- Get_Line_Start --
2531 --------------------
2533 function Get_Line_Start
2534 (Buf : Source_Buffer_Ptr;
2535 Loc : Source_Ptr) return Source_Ptr
2537 Cur_Loc : Source_Ptr := Loc;
2538 begin
2539 while Cur_Loc > Buf'First
2540 and then Buf (Cur_Loc - 1) /= ASCII.LF
2541 loop
2542 Cur_Loc := Cur_Loc - 1;
2543 end loop;
2545 return Cur_Loc;
2546 end Get_Line_Start;
2548 -----------
2549 -- Image --
2550 -----------
2552 function Image (X : Positive; Width : Positive) return String is
2553 Str : String (1 .. Width);
2554 Curr : Natural := X;
2555 begin
2556 for J in reverse 1 .. Width loop
2557 if Curr > 0 then
2558 Str (J) := Character'Val (Character'Pos ('0') + Curr mod 10);
2559 Curr := Curr / 10;
2560 else
2561 Str (J) := ' ';
2562 end if;
2563 end loop;
2565 return Str;
2566 end Image;
2568 ------------------
2569 -- Write_Buffer --
2570 ------------------
2572 procedure Write_Buffer
2573 (Buf : Source_Buffer_Ptr;
2574 First : Source_Ptr;
2575 Last : Source_Ptr)
2577 begin
2578 for Loc in First .. Last loop
2579 Write_Buffer_Char (Buf, Loc);
2580 end loop;
2581 end Write_Buffer;
2583 -----------------------
2584 -- Write_Buffer_Char --
2585 -----------------------
2587 procedure Write_Buffer_Char
2588 (Buf : Source_Buffer_Ptr;
2589 Loc : Source_Ptr)
2591 begin
2592 -- If the character ASCII.HT is not the last one in the file,
2593 -- output as many spaces as the character represents in the
2594 -- original source file.
2596 if Buf (Loc) = ASCII.HT
2597 and then Loc < Buf'Last
2598 then
2599 for X in Get_Column_Number (Loc) ..
2600 Get_Column_Number (Loc + 1) - 1
2601 loop
2602 Write_Char (' ');
2603 end loop;
2605 -- Otherwise output the character itself
2607 else
2608 Write_Char (Buf (Loc));
2609 end if;
2610 end Write_Buffer_Char;
2612 -----------------------
2613 -- Write_Line_Marker --
2614 -----------------------
2616 procedure Write_Line_Marker
2617 (Num : Pos;
2618 Mark : Boolean;
2619 Width : Positive)
2621 begin
2622 Write_Str (Image (Positive (Num), Width => Width));
2623 Write_Str ((if Mark then ">" else " ") & "|");
2624 end Write_Line_Marker;
2626 -- Local variables
2628 Loc : constant Source_Ptr := Span.Ptr;
2629 Line : constant Pos := Pos (Get_Physical_Line_Number (Loc));
2631 Col : constant Natural := Natural (Get_Column_Number (Loc));
2633 Fst : constant Source_Ptr := Span.First;
2634 Line_Fst : constant Pos :=
2635 Pos (Get_Physical_Line_Number (Fst));
2636 Col_Fst : constant Natural :=
2637 Natural (Get_Column_Number (Fst));
2638 Lst : constant Source_Ptr := Span.Last;
2639 Line_Lst : constant Pos :=
2640 Pos (Get_Physical_Line_Number (Lst));
2641 Col_Lst : constant Natural :=
2642 Natural (Get_Column_Number (Lst));
2644 Width : constant := 5;
2645 Buf : Source_Buffer_Ptr;
2646 Cur_Loc : Source_Ptr := Fst;
2647 Cur_Line : Pos := Line_Fst;
2649 -- Start of processing for Write_Source_Code_Lines
2651 begin
2652 if Loc >= First_Source_Ptr then
2653 Buf := Source_Text (Get_Source_File_Index (Loc));
2655 -- First line of the span with actual source code. We retrieve
2656 -- the beginning of the line instead of relying on Col_Fst, as
2657 -- ASCII.HT characters change column numbers by possibly more
2658 -- than one.
2660 Write_Line_Marker
2661 (Cur_Line,
2662 Line_Fst /= Line_Lst and then Cur_Line = Line,
2663 Width);
2664 Write_Buffer (Buf, Get_Line_Start (Buf, Cur_Loc), Cur_Loc - 1);
2666 -- Output the first/caret/last lines of the span, as well as
2667 -- lines that are directly above/below the caret if they complete
2668 -- the gap with first/last lines, otherwise use ... to denote
2669 -- intermediate lines.
2671 -- If the span is on one line and not a simple source location,
2672 -- color it appropriately.
2674 if Line_Fst = Line_Lst
2675 and then Col_Fst /= Col_Lst
2676 then
2677 Write_Str (SGR_Span);
2678 end if;
2680 declare
2681 function Do_Write_Line (Cur_Line : Pos) return Boolean is
2682 (Cur_Line in Line_Fst | Line | Line_Lst
2683 or else
2684 (Cur_Line = Line_Fst + 1 and then Cur_Line = Line - 1)
2685 or else
2686 (Cur_Line = Line + 1 and then Cur_Line = Line_Lst - 1));
2687 begin
2688 while Cur_Loc <= Buf'Last
2689 and then Cur_Loc <= Lst
2690 loop
2691 if Do_Write_Line (Cur_Line) then
2692 Write_Buffer_Char (Buf, Cur_Loc);
2693 end if;
2695 if Buf (Cur_Loc) = ASCII.LF then
2696 Cur_Line := Cur_Line + 1;
2698 -- Output ... for skipped lines
2700 if (Cur_Line = Line
2701 and then not Do_Write_Line (Cur_Line - 1))
2702 or else
2703 (Cur_Line = Line + 1
2704 and then not Do_Write_Line (Cur_Line))
2705 then
2706 Write_Str ((1 .. Width - 3 => ' ') & "... | ...");
2707 Write_Eol;
2708 end if;
2710 -- Display the line marker if the line should be
2711 -- displayed.
2713 if Do_Write_Line (Cur_Line) then
2714 Write_Line_Marker
2715 (Cur_Line,
2716 Line_Fst /= Line_Lst and then Cur_Line = Line,
2717 Width);
2718 end if;
2719 end if;
2721 Cur_Loc := Cur_Loc + 1;
2722 end loop;
2723 end;
2725 if Line_Fst = Line_Lst
2726 and then Col_Fst /= Col_Lst
2727 then
2728 Write_Str (SGR_Reset);
2729 end if;
2731 -- Output the rest of the last line of the span
2733 Write_Buffer (Buf, Cur_Loc, Get_Line_End (Buf, Cur_Loc));
2735 -- If the span is on one line, output a second line with caret
2736 -- sign pointing to location Loc
2738 if Line_Fst = Line_Lst then
2739 Write_Str (String'(1 .. Width => ' '));
2740 Write_Str (" |");
2741 Write_Str (String'(1 .. Col_Fst - 1 => ' '));
2743 Write_Str (SGR_Span);
2745 Write_Str (String'(Col_Fst .. Col - 1 => '~'));
2746 Write_Str ("^");
2747 Write_Str (String'(Col + 1 .. Col_Lst => '~'));
2749 -- If the span is really just a location, add the word "here"
2750 -- to clarify this is the location for the message.
2752 if Col_Fst = Col_Lst then
2753 Write_Str (" here");
2754 end if;
2756 Write_Str (SGR_Reset);
2758 Write_Eol;
2759 end if;
2760 end if;
2761 end Write_Source_Code_Lines;
2763 -- Local variables
2765 E : Error_Msg_Id;
2766 Err_Flag : Boolean;
2767 Use_Prefix : Boolean;
2769 -- Start of processing for Output_Messages
2771 begin
2772 -- Error if Finalize has not been called
2774 if not Finalize_Called then
2775 raise Program_Error;
2776 end if;
2778 -- Reset current error source file if the main unit has a pragma
2779 -- Source_Reference. This ensures outputting the proper name of
2780 -- the source file in this situation.
2782 if Main_Source_File <= No_Source_File
2783 or else Num_SRef_Pragmas (Main_Source_File) /= 0
2784 then
2785 Current_Error_Source_File := No_Source_File;
2786 end if;
2788 if Opt.JSON_Output then
2789 Set_Standard_Error;
2791 E := First_Error_Msg;
2793 -- Find first printable message
2795 while E /= No_Error_Msg and then Errors.Table (E).Deleted loop
2796 E := Errors.Table (E).Next;
2797 end loop;
2799 Write_Char ('[');
2801 if E /= No_Error_Msg then
2803 Output_JSON_Message (E);
2805 E := Errors.Table (E).Next;
2807 -- Skip deleted messages.
2808 -- Also skip continuation messages, as they have already been
2809 -- printed along the message they're attached to.
2811 while E /= No_Error_Msg
2812 and then not Errors.Table (E).Deleted
2813 and then not Errors.Table (E).Msg_Cont
2814 loop
2815 Write_Char (',');
2816 Output_JSON_Message (E);
2817 E := Errors.Table (E).Next;
2818 end loop;
2819 end if;
2821 Write_Char (']');
2823 Set_Standard_Output;
2825 -- Brief Error mode
2827 elsif Brief_Output or (not Full_List and not Verbose_Mode) then
2828 Set_Standard_Error;
2830 E := First_Error_Msg;
2831 while E /= No_Error_Msg loop
2833 -- If -gnatdF is used, separate main messages from previous
2834 -- messages with a newline (unless it is an info message) and
2835 -- make continuation messages follow the main message with only
2836 -- an indentation of two space characters, without repeating
2837 -- file:line:col: prefix.
2839 Use_Prefix :=
2840 not (Debug_Flag_FF and then Errors.Table (E).Msg_Cont);
2842 if not Errors.Table (E).Deleted and then not Debug_Flag_KK then
2844 if Debug_Flag_FF then
2845 if Errors.Table (E).Msg_Cont then
2846 Write_Str (" ");
2847 elsif not Errors.Table (E).Info then
2848 Write_Eol;
2849 end if;
2850 end if;
2852 if Use_Prefix then
2853 Write_Str (SGR_Locus);
2855 if Full_Path_Name_For_Brief_Errors then
2856 Write_Name (Full_Ref_Name (Errors.Table (E).Sfile));
2857 else
2858 Write_Name (Reference_Name (Errors.Table (E).Sfile));
2859 end if;
2861 Write_Char (':');
2862 Write_Int (Int (Physical_To_Logical
2863 (Errors.Table (E).Line,
2864 Errors.Table (E).Sfile)));
2865 Write_Char (':');
2867 if Errors.Table (E).Col < 10 then
2868 Write_Char ('0');
2869 end if;
2871 Write_Int (Int (Errors.Table (E).Col));
2872 Write_Str (": ");
2874 Write_Str (SGR_Reset);
2875 end if;
2877 Output_Msg_Text (E);
2878 Write_Eol;
2880 -- If -gnatdF is used, write the source code line corresponding
2881 -- to the location of the main message (unless it is an info
2882 -- message). Also write the source code line corresponding to
2883 -- an insertion location inside continuation messages.
2885 if Debug_Flag_FF
2886 and then not Errors.Table (E).Info
2887 then
2888 if Errors.Table (E).Msg_Cont then
2889 declare
2890 Loc : constant Source_Ptr :=
2891 Errors.Table (E).Insertion_Sloc;
2892 begin
2893 if Loc /= No_Location then
2894 Write_Source_Code_Lines
2895 (To_Span (Loc), SGR_Span => SGR_Note);
2896 end if;
2897 end;
2899 else
2900 declare
2901 SGR_Span : constant String :=
2902 (if Errors.Table (E).Info then SGR_Note
2903 elsif Errors.Table (E).Warn
2904 and then not Errors.Table (E).Warn_Err
2905 then SGR_Warning
2906 else SGR_Error);
2907 begin
2908 Write_Source_Code_Lines
2909 (Errors.Table (E).Sptr, SGR_Span);
2910 end;
2911 end if;
2912 end if;
2913 end if;
2915 E := Errors.Table (E).Next;
2916 end loop;
2918 Set_Standard_Output;
2919 end if;
2921 -- Full source listing case
2923 if Full_List then
2924 List_Pragmas_Index := 1;
2925 List_Pragmas_Mode := True;
2926 E := First_Error_Msg;
2928 -- Normal case, to stdout (copyright notice already output)
2930 if Full_List_File_Name = null then
2931 if not Debug_Flag_7 then
2932 Write_Eol;
2933 end if;
2935 -- Output to file
2937 else
2938 Create_List_File_Access.all (Full_List_File_Name.all);
2939 Set_Special_Output (Write_List_Info_Access.all'Access);
2941 -- Write copyright notice to file
2943 if not Debug_Flag_7 then
2944 Write_Str ("GNAT ");
2945 Write_Str (Gnat_Version_String);
2946 Write_Eol;
2947 Write_Str ("Copyright 1992-" &
2948 Current_Year &
2949 ", Free Software Foundation, Inc.");
2950 Write_Eol;
2951 end if;
2952 end if;
2954 -- First list extended main source file units with errors
2956 for U in Main_Unit .. Last_Unit loop
2957 if In_Extended_Main_Source_Unit (Cunit_Entity (U))
2959 -- If debug flag d.m is set, only the main source is listed
2961 and then (U = Main_Unit or else not Debug_Flag_Dot_M)
2963 -- If the unit of the entity does not come from source, it is
2964 -- an implicit subprogram declaration for a child subprogram.
2965 -- Do not emit errors for it, they are listed with the body.
2967 and then
2968 (No (Cunit_Entity (U))
2969 or else Comes_From_Source (Cunit_Entity (U))
2970 or else not Is_Subprogram (Cunit_Entity (U)))
2972 -- If the compilation unit associated with this unit does not
2973 -- come from source, it means it is an instantiation that should
2974 -- not be included in the source listing.
2976 and then Comes_From_Source (Cunit (U))
2977 then
2978 declare
2979 Sfile : constant Source_File_Index := Source_Index (U);
2981 begin
2982 Write_Eol;
2984 -- Only write the header if Sfile is known
2986 if Sfile > No_Source_File then
2987 Write_Header (Sfile);
2988 Write_Eol;
2989 end if;
2991 -- Normally, we don't want an "error messages from file"
2992 -- message when listing the entire file, so we set the
2993 -- current source file as the current error source file.
2994 -- However, the old style of doing things was to list this
2995 -- message if pragma Source_Reference is present, even for
2996 -- the main unit. Since the purpose of the -gnatd.m switch
2997 -- is to duplicate the old behavior, we skip the reset if
2998 -- this debug flag is set.
3000 if not Debug_Flag_Dot_M then
3001 Current_Error_Source_File := Sfile;
3002 end if;
3004 -- Only output the listing if Sfile is known, to avoid
3005 -- crashing the compiler.
3007 if Sfile > No_Source_File then
3008 for N in 1 .. Last_Source_Line (Sfile) loop
3009 while E /= No_Error_Msg
3010 and then Errors.Table (E).Deleted
3011 loop
3012 E := Errors.Table (E).Next;
3013 end loop;
3015 Err_Flag :=
3016 E /= No_Error_Msg
3017 and then Errors.Table (E).Line = N
3018 and then Errors.Table (E).Sfile = Sfile;
3020 Output_Source_Line (N, Sfile, Err_Flag);
3022 if Err_Flag then
3023 Output_Error_Msgs (E);
3025 if not Debug_Flag_2 then
3026 Write_Eol;
3027 end if;
3028 end if;
3029 end loop;
3030 end if;
3031 end;
3032 end if;
3033 end loop;
3035 -- Then output errors, if any, for subsidiary units not in the
3036 -- main extended unit.
3038 -- Note: if debug flag d.m set, include errors for any units other
3039 -- than the main unit in the extended source unit (e.g. spec and
3040 -- subunits for a body).
3042 while E /= No_Error_Msg
3043 and then (not In_Extended_Main_Source_Unit
3044 (Errors.Table (E).Sptr.Ptr)
3045 or else
3046 (Debug_Flag_Dot_M
3047 and then Get_Source_Unit
3048 (Errors.Table (E).Sptr.Ptr) /= Main_Unit))
3049 loop
3050 if Errors.Table (E).Deleted then
3051 E := Errors.Table (E).Next;
3053 else
3054 Write_Eol;
3055 Output_Source_Line
3056 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3057 Output_Error_Msgs (E);
3058 end if;
3059 end loop;
3061 -- If output to file, write extra copy of error summary to the
3062 -- output file, and then close it.
3064 if Full_List_File_Name /= null then
3065 Write_Error_Summary;
3066 Write_Max_Errors;
3067 Close_List_File_Access.all;
3068 Cancel_Special_Output;
3069 end if;
3070 end if;
3072 -- Verbose mode (error lines only with error flags). Normally this is
3073 -- ignored in full list mode, unless we are listing to a file, in which
3074 -- case we still generate -gnatv output to standard output.
3076 if Verbose_Mode
3077 and then (not Full_List or else Full_List_File_Name /= null)
3078 then
3079 Write_Eol;
3081 -- Output the header only when Main_Source_File is known
3083 if Main_Source_File > No_Source_File then
3084 Write_Header (Main_Source_File);
3085 end if;
3087 E := First_Error_Msg;
3089 -- Loop through error lines
3091 while E /= No_Error_Msg loop
3092 if Errors.Table (E).Deleted then
3093 E := Errors.Table (E).Next;
3094 else
3095 Write_Eol;
3096 Output_Source_Line
3097 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3098 Output_Error_Msgs (E);
3099 end if;
3100 end loop;
3101 end if;
3103 -- Output error summary if verbose or full list mode
3105 if Verbose_Mode or else Full_List then
3106 Write_Error_Summary;
3107 end if;
3109 if not Opt.JSON_Output then
3110 Write_Max_Errors;
3111 end if;
3113 -- Even though Warning_Info_Messages are a subclass of warnings, they
3114 -- must not be treated as errors when -gnatwe is in effect.
3116 if Warning_Mode = Treat_As_Error then
3117 declare
3118 Compile_Time_Pragma_Warnings : constant Int :=
3119 Count_Compile_Time_Pragma_Warnings;
3120 begin
3121 Total_Errors_Detected := Total_Errors_Detected + Warnings_Detected
3122 - Warning_Info_Messages - Compile_Time_Pragma_Warnings;
3123 Warnings_Detected :=
3124 Warning_Info_Messages + Compile_Time_Pragma_Warnings;
3125 end;
3126 end if;
3127 end Output_Messages;
3129 ------------------------
3130 -- Output_Source_Line --
3131 ------------------------
3133 procedure Output_Source_Line
3134 (L : Physical_Line_Number;
3135 Sfile : Source_File_Index;
3136 Errs : Boolean)
3138 S : Source_Ptr;
3139 C : Character;
3141 Line_Number_Output : Boolean := False;
3142 -- Set True once line number is output
3144 Empty_Line : Boolean := True;
3145 -- Set False if line includes at least one character
3147 begin
3148 if Sfile /= Current_Error_Source_File then
3149 Write_Str ("==============Error messages for ");
3151 case Sinput.File_Type (Sfile) is
3152 when Sinput.Src =>
3153 Write_Str ("source");
3155 when Sinput.Config =>
3156 Write_Str ("configuration pragmas");
3158 when Sinput.Def =>
3159 Write_Str ("symbol definition");
3161 when Sinput.Preproc =>
3162 Write_Str ("preprocessing data");
3163 end case;
3165 Write_Str (" file: ");
3166 Write_Name (Full_File_Name (Sfile));
3167 Write_Eol;
3169 if Num_SRef_Pragmas (Sfile) > 0 then
3170 Write_Str ("--------------Line numbers from file: ");
3171 Write_Name (Full_Ref_Name (Sfile));
3172 Write_Str (" (starting at line ");
3173 Write_Int (Int (First_Mapped_Line (Sfile)));
3174 Write_Char (')');
3175 Write_Eol;
3176 end if;
3178 Current_Error_Source_File := Sfile;
3179 end if;
3181 if Errs or List_Pragmas_Mode then
3182 Output_Line_Number (Physical_To_Logical (L, Sfile));
3183 Line_Number_Output := True;
3184 end if;
3186 S := Line_Start (L, Sfile);
3188 loop
3189 C := Source_Text (Sfile) (S);
3190 exit when C = ASCII.LF or else C = ASCII.CR or else C = EOF;
3192 -- Deal with matching entry in List_Pragmas table
3194 if Full_List
3195 and then List_Pragmas_Index <= List_Pragmas.Last
3196 and then S = List_Pragmas.Table (List_Pragmas_Index).Ploc
3197 then
3198 case List_Pragmas.Table (List_Pragmas_Index).Ptyp is
3199 when Page =>
3200 Write_Char (C);
3202 -- Ignore if on line with errors so that error flags
3203 -- get properly listed with the error line .
3205 if not Errs then
3206 Write_Char (ASCII.FF);
3207 end if;
3209 when List_On =>
3210 List_Pragmas_Mode := True;
3212 if not Line_Number_Output then
3213 Output_Line_Number (Physical_To_Logical (L, Sfile));
3214 Line_Number_Output := True;
3215 end if;
3217 Write_Char (C);
3219 when List_Off =>
3220 Write_Char (C);
3221 List_Pragmas_Mode := False;
3222 end case;
3224 List_Pragmas_Index := List_Pragmas_Index + 1;
3226 -- Normal case (no matching entry in List_Pragmas table)
3228 else
3229 if Errs or List_Pragmas_Mode then
3230 Write_Char (C);
3231 end if;
3232 end if;
3234 Empty_Line := False;
3235 S := S + 1;
3236 end loop;
3238 -- If we have output a source line, then add the line terminator, with
3239 -- training spaces preserved (so we output the line exactly as input).
3241 if Line_Number_Output then
3242 if Empty_Line then
3243 Write_Eol;
3244 else
3245 Write_Eol_Keep_Blanks;
3246 end if;
3247 end if;
3248 end Output_Source_Line;
3250 -----------------------------
3251 -- Remove_Warning_Messages --
3252 -----------------------------
3254 procedure Remove_Warning_Messages (N : Node_Id) is
3256 function Check_For_Warning (N : Node_Id) return Traverse_Result;
3257 -- This function checks one node for a possible warning message
3259 procedure Check_All_Warnings is new Traverse_Proc (Check_For_Warning);
3260 -- This defines the traversal operation
3262 -----------------------
3263 -- Check_For_Warning --
3264 -----------------------
3266 function Check_For_Warning (N : Node_Id) return Traverse_Result is
3267 Loc : constant Source_Ptr := Sloc (N);
3268 E : Error_Msg_Id;
3270 function To_Be_Removed (E : Error_Msg_Id) return Boolean;
3271 -- Returns True for a message that is to be removed. Also adjusts
3272 -- warning count appropriately.
3274 -------------------
3275 -- To_Be_Removed --
3276 -------------------
3278 function To_Be_Removed (E : Error_Msg_Id) return Boolean is
3279 begin
3280 if E /= No_Error_Msg
3282 -- Don't remove if location does not match
3284 and then Errors.Table (E).Optr = Loc
3286 -- Don't remove if not warning/info message. Note that we do
3287 -- not remove style messages here. They are warning messages
3288 -- but not ones we want removed in this context.
3290 and then (Errors.Table (E).Warn
3291 or else
3292 Errors.Table (E).Warn_Runtime_Raise)
3294 -- Don't remove unconditional messages
3296 and then not Errors.Table (E).Uncond
3297 then
3298 if Errors.Table (E).Warn then
3299 Warnings_Detected := Warnings_Detected - 1;
3300 end if;
3302 if Errors.Table (E).Info then
3303 Warning_Info_Messages := Warning_Info_Messages - 1;
3304 end if;
3306 return True;
3308 -- No removal required
3310 else
3311 return False;
3312 end if;
3313 end To_Be_Removed;
3315 -- Start of processing for Check_For_Warnings
3317 begin
3318 while To_Be_Removed (First_Error_Msg) loop
3319 First_Error_Msg := Errors.Table (First_Error_Msg).Next;
3320 end loop;
3322 if First_Error_Msg = No_Error_Msg then
3323 Last_Error_Msg := No_Error_Msg;
3324 end if;
3326 E := First_Error_Msg;
3327 while E /= No_Error_Msg loop
3328 while To_Be_Removed (Errors.Table (E).Next) loop
3329 Errors.Table (E).Next :=
3330 Errors.Table (Errors.Table (E).Next).Next;
3332 if Errors.Table (E).Next = No_Error_Msg then
3333 Last_Error_Msg := E;
3334 end if;
3335 end loop;
3337 E := Errors.Table (E).Next;
3338 end loop;
3340 if Nkind (N) = N_Raise_Constraint_Error
3341 and then Is_Rewrite_Substitution (N)
3342 and then No (Condition (N))
3343 then
3344 -- Warnings may have been posted on subexpressions of the original
3345 -- tree. We place the original node back on the tree to remove
3346 -- those warnings, whose sloc do not match those of any node in
3347 -- the current tree. Given that we are in unreachable code, this
3348 -- modification to the tree is harmless.
3350 if Is_List_Member (N) then
3351 Set_Condition (N, Original_Node (N));
3352 Check_All_Warnings (Condition (N));
3353 else
3354 Rewrite (N, Original_Node (N));
3355 Check_All_Warnings (N);
3356 end if;
3357 end if;
3359 return OK;
3360 end Check_For_Warning;
3362 -- Start of processing for Remove_Warning_Messages
3364 begin
3365 if Warnings_Detected /= 0 then
3366 Check_All_Warnings (N);
3367 end if;
3368 end Remove_Warning_Messages;
3370 procedure Remove_Warning_Messages (L : List_Id) is
3371 Stat : Node_Id;
3372 begin
3373 Stat := First (L);
3374 while Present (Stat) loop
3375 Remove_Warning_Messages (Stat);
3376 Next (Stat);
3377 end loop;
3378 end Remove_Warning_Messages;
3380 --------------------
3381 -- Reset_Warnings --
3382 --------------------
3384 procedure Reset_Warnings is
3385 begin
3386 Warnings_Treated_As_Errors := 0;
3387 Warnings_Detected := 0;
3388 Warning_Info_Messages := 0;
3389 Warnings_As_Errors_Count := 0;
3390 end Reset_Warnings;
3392 ----------------------
3393 -- Adjust_Name_Case --
3394 ----------------------
3396 procedure Adjust_Name_Case
3397 (Buf : in out Bounded_String;
3398 Loc : Source_Ptr)
3400 Src_Ind : constant Source_File_Index := Get_Source_File_Index (Loc);
3401 Sbuffer : Source_Buffer_Ptr;
3402 Ref_Ptr : Integer;
3403 Src_Ptr : Source_Ptr;
3405 begin
3406 -- We have an all lower case name from Namet, and now we want to set
3407 -- the appropriate case. If possible we copy the actual casing from
3408 -- the source. If not we use standard identifier casing.
3410 Ref_Ptr := 1;
3411 Src_Ptr := Loc;
3413 -- For standard locations, always use mixed case
3415 if Loc <= No_Location then
3416 Set_Casing (Buf, Mixed_Case);
3418 else
3419 -- Determine if the reference we are dealing with corresponds to text
3420 -- at the point of the error reference. This will often be the case
3421 -- for simple identifier references, and is the case where we can
3422 -- copy the casing from the source.
3424 Sbuffer := Source_Text (Src_Ind);
3426 while Ref_Ptr <= Buf.Length loop
3427 exit when
3428 Fold_Lower (Sbuffer (Src_Ptr)) /=
3429 Fold_Lower (Buf.Chars (Ref_Ptr));
3430 Ref_Ptr := Ref_Ptr + 1;
3431 Src_Ptr := Src_Ptr + 1;
3432 end loop;
3434 -- If we get through the loop without a mismatch, then output the
3435 -- name the way it is cased in the source program.
3437 if Ref_Ptr > Buf.Length then
3438 Src_Ptr := Loc;
3440 for J in 1 .. Buf.Length loop
3441 Buf.Chars (J) := Sbuffer (Src_Ptr);
3442 Src_Ptr := Src_Ptr + 1;
3443 end loop;
3445 -- Otherwise set the casing using the default identifier casing
3447 else
3448 Set_Casing (Buf, Identifier_Casing (Src_Ind));
3449 end if;
3450 end if;
3451 end Adjust_Name_Case;
3453 ---------------------------
3454 -- Set_Identifier_Casing --
3455 ---------------------------
3457 procedure Set_Identifier_Casing
3458 (Identifier_Name : System.Address;
3459 File_Name : System.Address)
3461 Ident : constant Big_String_Ptr := To_Big_String_Ptr (Identifier_Name);
3462 File : constant Big_String_Ptr := To_Big_String_Ptr (File_Name);
3463 Flen : Natural;
3465 Desired_Case : Casing_Type := Mixed_Case;
3466 -- Casing required for result. Default value of Mixed_Case is used if
3467 -- for some reason we cannot find the right file name in the table.
3469 begin
3470 -- Get length of file name
3472 Flen := 0;
3473 while File (Flen + 1) /= ASCII.NUL loop
3474 Flen := Flen + 1;
3475 end loop;
3477 -- Loop through file names to find matching one. This is a bit slow, but
3478 -- we only do it in error situations so it is not so terrible. Note that
3479 -- if the loop does not exit, then the desired case will be left set to
3480 -- Mixed_Case, this can happen if the name was not in canonical form.
3482 for J in 1 .. Last_Source_File loop
3483 Get_Name_String (Full_Debug_Name (J));
3485 if Name_Len = Flen
3486 and then Name_Buffer (1 .. Name_Len) = String (File (1 .. Flen))
3487 then
3488 Desired_Case := Identifier_Casing (J);
3489 exit;
3490 end if;
3491 end loop;
3493 -- Copy identifier as given to Name_Buffer
3495 for J in Name_Buffer'Range loop
3496 Name_Buffer (J) := Ident (J);
3498 if Name_Buffer (J) = ASCII.NUL then
3499 Name_Len := J - 1;
3500 exit;
3501 end if;
3502 end loop;
3504 Set_Casing (Desired_Case);
3505 end Set_Identifier_Casing;
3507 -----------------------
3508 -- Set_Ignore_Errors --
3509 -----------------------
3511 procedure Set_Ignore_Errors (To : Boolean) is
3512 begin
3513 Errors_Must_Be_Ignored := To;
3514 end Set_Ignore_Errors;
3516 ------------------------------
3517 -- Set_Msg_Insertion_Column --
3518 ------------------------------
3520 procedure Set_Msg_Insertion_Column is
3521 begin
3522 if RM_Column_Check then
3523 Set_Msg_Str (" in column ");
3524 Set_Msg_Int (Int (Error_Msg_Col) + 1);
3525 end if;
3526 end Set_Msg_Insertion_Column;
3528 ----------------------------
3529 -- Set_Msg_Insertion_Node --
3530 ----------------------------
3532 procedure Set_Msg_Insertion_Node is
3533 K : Node_Kind;
3535 begin
3536 Suppress_Message :=
3537 Error_Msg_Node_1 = Error
3538 or else Error_Msg_Node_1 = Any_Type;
3540 if Error_Msg_Node_1 = Empty then
3541 Set_Msg_Blank_Conditional;
3542 Set_Msg_Str ("<empty>");
3544 elsif Error_Msg_Node_1 = Error then
3545 Set_Msg_Blank;
3546 Set_Msg_Str ("<error>");
3548 elsif Error_Msg_Node_1 = Standard_Void_Type then
3549 Set_Msg_Blank;
3550 Set_Msg_Str ("procedure name");
3552 elsif Nkind (Error_Msg_Node_1) in N_Entity
3553 and then Ekind (Error_Msg_Node_1) = E_Anonymous_Access_Subprogram_Type
3554 then
3555 Set_Msg_Blank;
3556 Set_Msg_Str ("access to subprogram");
3558 else
3559 Set_Msg_Blank_Conditional;
3561 -- Output name
3563 K := Nkind (Error_Msg_Node_1);
3565 -- If we have operator case, skip quotes since name of operator
3566 -- itself will supply the required quotations. An operator can be an
3567 -- applied use in an expression or an explicit operator symbol, or an
3568 -- identifier whose name indicates it is an operator.
3570 if K in N_Op
3571 or else K = N_Operator_Symbol
3572 or else K = N_Defining_Operator_Symbol
3573 or else ((K = N_Identifier or else K = N_Defining_Identifier)
3574 and then Is_Operator_Name (Chars (Error_Msg_Node_1)))
3575 then
3576 Set_Msg_Node (Error_Msg_Node_1);
3578 -- Normal case, not an operator, surround with quotes
3580 else
3581 Set_Msg_Quote;
3582 Set_Qualification (Error_Msg_Qual_Level, Error_Msg_Node_1);
3583 Set_Msg_Node (Error_Msg_Node_1);
3584 Set_Msg_Quote;
3585 end if;
3586 end if;
3588 -- The following assignment ensures that further ampersand insertion
3589 -- characters will correspond to the Error_Msg_Node_# parameter.
3591 Error_Msg_Node_1 := Error_Msg_Node_2;
3592 Error_Msg_Node_2 := Error_Msg_Node_3;
3593 Error_Msg_Node_3 := Error_Msg_Node_4;
3594 Error_Msg_Node_4 := Error_Msg_Node_5;
3595 Error_Msg_Node_5 := Error_Msg_Node_6;
3596 end Set_Msg_Insertion_Node;
3598 --------------------------------------
3599 -- Set_Msg_Insertion_Type_Reference --
3600 --------------------------------------
3602 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr) is
3603 Ent : Entity_Id;
3605 begin
3606 Set_Msg_Blank;
3608 if Error_Msg_Node_1 = Standard_Void_Type then
3609 Set_Msg_Str ("package or procedure name");
3610 return;
3612 elsif Error_Msg_Node_1 = Standard_Exception_Type then
3613 Set_Msg_Str ("exception name");
3614 return;
3616 elsif Error_Msg_Node_1 = Any_Array
3617 or else Error_Msg_Node_1 = Any_Boolean
3618 or else Error_Msg_Node_1 = Any_Character
3619 or else Error_Msg_Node_1 = Any_Composite
3620 or else Error_Msg_Node_1 = Any_Discrete
3621 or else Error_Msg_Node_1 = Any_Fixed
3622 or else Error_Msg_Node_1 = Any_Integer
3623 or else Error_Msg_Node_1 = Any_Modular
3624 or else Error_Msg_Node_1 = Any_Numeric
3625 or else Error_Msg_Node_1 = Any_Real
3626 or else Error_Msg_Node_1 = Any_Scalar
3627 or else Error_Msg_Node_1 = Any_String
3628 then
3629 Get_Unqualified_Decoded_Name_String (Chars (Error_Msg_Node_1));
3630 Set_Msg_Name_Buffer;
3631 return;
3633 elsif Error_Msg_Node_1 = Universal_Integer then
3634 Set_Msg_Str ("type universal integer");
3635 return;
3637 elsif Error_Msg_Node_1 = Universal_Real then
3638 Set_Msg_Str ("type universal real");
3639 return;
3641 elsif Error_Msg_Node_1 = Universal_Fixed then
3642 Set_Msg_Str ("type universal fixed");
3643 return;
3645 elsif Error_Msg_Node_1 = Universal_Access then
3646 Set_Msg_Str ("type universal access");
3647 return;
3648 end if;
3650 -- Special case of anonymous array
3652 if Nkind (Error_Msg_Node_1) in N_Entity
3653 and then Is_Array_Type (Error_Msg_Node_1)
3654 and then Present (Related_Array_Object (Error_Msg_Node_1))
3655 then
3656 Set_Msg_Str ("type of ");
3657 Set_Msg_Node (Related_Array_Object (Error_Msg_Node_1));
3658 Set_Msg_Str (" declared");
3659 Set_Msg_Insertion_Line_Number
3660 (Sloc (Related_Array_Object (Error_Msg_Node_1)), Flag);
3661 return;
3662 end if;
3664 -- If we fall through, it is not a special case, so first output
3665 -- the name of the type, preceded by private for a private type
3667 if Is_Private_Type (Error_Msg_Node_1) then
3668 Set_Msg_Str ("private type ");
3669 else
3670 Set_Msg_Str ("type ");
3671 end if;
3673 Ent := Error_Msg_Node_1;
3675 if Is_Internal_Name (Chars (Ent)) then
3676 Unwind_Internal_Type (Ent);
3677 end if;
3679 -- Types in Standard are displayed as "Standard.name"
3681 if Sloc (Ent) <= Standard_Location then
3682 Set_Msg_Quote;
3683 Set_Msg_Str ("Standard.");
3684 Set_Msg_Node (Ent);
3685 Add_Class;
3686 Set_Msg_Quote;
3688 -- Types in other language defined units are displayed as
3689 -- "package-name.type-name"
3691 elsif Is_Predefined_Unit (Get_Source_Unit (Ent)) then
3692 Get_Unqualified_Decoded_Name_String
3693 (Unit_Name (Get_Source_Unit (Ent)));
3694 Name_Len := Name_Len - 2;
3695 Set_Msg_Blank_Conditional;
3696 Set_Msg_Quote;
3697 Set_Casing (Mixed_Case);
3698 Set_Msg_Name_Buffer;
3699 Set_Msg_Char ('.');
3700 Set_Casing (Mixed_Case);
3701 Set_Msg_Node (Ent);
3702 Add_Class;
3703 Set_Msg_Quote;
3705 -- All other types display as "type name" defined at line xxx
3706 -- possibly qualified if qualification is requested.
3708 else
3709 Set_Msg_Quote;
3710 Set_Qualification (Error_Msg_Qual_Level, Ent);
3711 Set_Msg_Node (Ent);
3712 Add_Class;
3714 -- If we did not print a name (e.g. in the case of an anonymous
3715 -- subprogram type), there is no name to print, so remove quotes.
3717 if Buffer_Ends_With ('"') then
3718 Buffer_Remove ('"');
3719 else
3720 Set_Msg_Quote;
3721 end if;
3722 end if;
3724 -- If the original type did not come from a predefined file, add the
3725 -- location where the type was defined.
3727 if Sloc (Error_Msg_Node_1) > Standard_Location
3728 and then
3729 not Is_Predefined_Unit (Get_Source_Unit (Error_Msg_Node_1))
3730 then
3731 Get_Name_String (Unit_File_Name (Get_Source_Unit (Error_Msg_Node_1)));
3732 Set_Msg_Str (" defined");
3733 Set_Msg_Insertion_Line_Number (Sloc (Error_Msg_Node_1), Flag);
3735 -- If it did come from a predefined file, deal with the case where
3736 -- this was a file with a generic instantiation from elsewhere.
3738 else
3739 if Sloc (Error_Msg_Node_1) > Standard_Location then
3740 declare
3741 Iloc : constant Source_Ptr :=
3742 Instantiation_Location (Sloc (Error_Msg_Node_1));
3744 begin
3745 if Iloc /= No_Location
3746 and then not Suppress_Instance_Location
3747 then
3748 Set_Msg_Str (" from instance");
3749 Set_Msg_Insertion_Line_Number (Iloc, Flag);
3750 end if;
3751 end;
3752 end if;
3753 end if;
3754 end Set_Msg_Insertion_Type_Reference;
3756 ---------------------------------
3757 -- Set_Msg_Insertion_Unit_Name --
3758 ---------------------------------
3760 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True) is
3761 begin
3762 if Error_Msg_Unit_1 = No_Unit_Name then
3763 null;
3765 elsif Error_Msg_Unit_1 = Error_Unit_Name then
3766 Set_Msg_Blank;
3767 Set_Msg_Str ("<error>");
3769 else
3770 Get_Unit_Name_String (Global_Name_Buffer, Error_Msg_Unit_1, Suffix);
3771 Set_Msg_Blank;
3772 Set_Msg_Quote;
3773 Set_Msg_Name_Buffer;
3774 Set_Msg_Quote;
3775 end if;
3777 -- The following assignment ensures that a second percent insertion
3778 -- character will correspond to the Error_Msg_Unit_2 parameter.
3780 Error_Msg_Unit_1 := Error_Msg_Unit_2;
3781 end Set_Msg_Insertion_Unit_Name;
3783 ------------------
3784 -- Set_Msg_Node --
3785 ------------------
3787 procedure Set_Msg_Node (Node : Node_Id) is
3788 Loc : Source_Ptr;
3789 Ent : Entity_Id;
3790 Nam : Name_Id;
3792 begin
3793 case Nkind (Node) is
3794 when N_Designator =>
3795 Set_Msg_Node (Name (Node));
3796 Set_Msg_Char ('.');
3797 Set_Msg_Node (Identifier (Node));
3798 return;
3800 when N_Defining_Program_Unit_Name =>
3801 Set_Msg_Node (Name (Node));
3802 Set_Msg_Char ('.');
3803 Set_Msg_Node (Defining_Identifier (Node));
3804 return;
3806 when N_Expanded_Name
3807 | N_Selected_Component
3809 Set_Msg_Node (Prefix (Node));
3810 Set_Msg_Char ('.');
3811 Set_Msg_Node (Selector_Name (Node));
3812 return;
3814 when others =>
3815 null;
3816 end case;
3818 -- The only remaining possibilities are identifiers, defining
3819 -- identifiers, pragmas, and pragma argument associations.
3821 if Nkind (Node) = N_Pragma then
3822 Nam := Pragma_Name (Node);
3823 Loc := Sloc (Node);
3825 -- The other cases have Chars fields
3827 -- First deal with internal names, which generally represent something
3828 -- gone wrong. First attempt: if this is a rewritten node that rewrites
3829 -- something with a Chars field that is not an internal name, use that.
3831 elsif Is_Internal_Name (Chars (Node))
3832 and then Nkind (Original_Node (Node)) in N_Has_Chars
3833 and then not Is_Internal_Name (Chars (Original_Node (Node)))
3834 then
3835 Nam := Chars (Original_Node (Node));
3836 Loc := Sloc (Original_Node (Node));
3838 -- Another shot for internal names, in the case of internal type names,
3839 -- we try to find a reasonable representation for the external name.
3841 elsif Is_Internal_Name (Chars (Node))
3842 and then
3843 ((Is_Entity_Name (Node)
3844 and then Present (Entity (Node))
3845 and then Is_Type (Entity (Node)))
3846 or else
3847 (Nkind (Node) = N_Defining_Identifier and then Is_Type (Node)))
3848 then
3849 if Nkind (Node) = N_Identifier then
3850 Ent := Entity (Node);
3851 else
3852 Ent := Node;
3853 end if;
3855 Loc := Sloc (Ent);
3857 -- If the type is the designated type of an access_to_subprogram,
3858 -- then there is no name to provide in the call.
3860 if Ekind (Ent) = E_Subprogram_Type then
3861 return;
3863 -- Otherwise, we will be able to find some kind of name to output
3865 else
3866 Unwind_Internal_Type (Ent);
3867 Nam := Chars (Ent);
3868 end if;
3870 -- If not internal name, or if we could not find a reasonable possible
3871 -- substitution for the internal name, just use name in Chars field.
3873 else
3874 Nam := Chars (Node);
3875 Loc := Sloc (Node);
3876 end if;
3878 -- At this stage, the name to output is in Nam
3880 Get_Unqualified_Decoded_Name_String (Nam);
3882 -- Remove trailing upper case letters from the name (useful for
3883 -- dealing with some cases of internal names).
3885 while Name_Len > 1 and then Name_Buffer (Name_Len) in 'A' .. 'Z' loop
3886 Name_Len := Name_Len - 1;
3887 end loop;
3889 -- If we have any of the names from standard that start with the
3890 -- characters "any " (e.g. Any_Type), then kill the message since
3891 -- almost certainly it is a junk cascaded message.
3893 if Name_Len > 4
3894 and then Name_Buffer (1 .. 4) = "any "
3895 then
3896 Kill_Message := True;
3897 end if;
3899 -- If we still have an internal name, kill the message (will only
3900 -- work if we already had errors!)
3902 if Is_Internal_Name then
3903 Kill_Message := True;
3904 end if;
3905 -- Remaining step is to adjust casing and possibly add 'Class
3907 Adjust_Name_Case (Global_Name_Buffer, Loc);
3908 Set_Msg_Name_Buffer;
3909 Add_Class;
3910 end Set_Msg_Node;
3912 ------------------
3913 -- Set_Msg_Text --
3914 ------------------
3916 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is
3917 C : Character; -- Current character
3918 P : Natural; -- Current index;
3920 procedure Skip_Msg_Insertion_Warning (C : Character);
3921 -- Skip the ? ?? ?x? ?*? ?$? insertion sequences (and the same
3922 -- sequences using < instead of ?). The caller has already bumped
3923 -- the pointer past the initial ? or < and C is set to this initial
3924 -- character (? or <). This procedure skips past the rest of the
3925 -- sequence. We do not need to set Msg_Insertion_Char, since this
3926 -- was already done during the message prescan.
3927 -- No validity check is performed as the insertion sequence is
3928 -- supposed to be sane. See Prescan_Message.Parse_Message_Class in
3929 -- erroutc.adb for the validity checks.
3931 --------------------------------
3932 -- Skip_Msg_Insertion_Warning --
3933 --------------------------------
3935 procedure Skip_Msg_Insertion_Warning (C : Character) is
3936 begin
3937 if P <= Text'Last and then Text (P) = C then
3938 P := P + 1;
3940 elsif P < Text'Last and then Text (P + 1) = C
3941 and then Text (P) in 'a' .. 'z' | '*' | '$'
3942 then
3943 P := P + 2;
3945 elsif P + 1 < Text'Last and then Text (P + 2) = C
3946 and then Text (P) in '.' | '_'
3947 and then Text (P + 1) in 'a' .. 'z'
3948 then
3949 P := P + 3;
3950 end if;
3951 end Skip_Msg_Insertion_Warning;
3953 -- Start of processing for Set_Msg_Text
3955 begin
3956 Manual_Quote_Mode := False;
3957 Msglen := 0;
3958 Flag_Source := Get_Source_File_Index (Flag);
3960 -- Skip info: at start, we have recorded this in Is_Info_Msg, and this
3961 -- will be used (Info field in error message object) to put back the
3962 -- string when it is printed. We need to do this, or we get confused
3963 -- with instantiation continuations.
3965 if Text'Length > 6
3966 and then Text (Text'First .. Text'First + 5) = "info: "
3967 then
3968 P := Text'First + 6;
3969 else
3970 P := Text'First;
3971 end if;
3973 -- Loop through characters of message
3975 while P <= Text'Last loop
3976 C := Text (P);
3977 P := P + 1;
3979 -- Check for insertion character or sequence
3981 case C is
3982 when '%' =>
3983 if P <= Text'Last and then Text (P) = '%' then
3984 P := P + 1;
3985 Set_Msg_Insertion_Name_Literal;
3986 else
3987 Set_Msg_Insertion_Name;
3988 end if;
3990 when '$' =>
3991 if P <= Text'Last and then Text (P) = '$' then
3992 P := P + 1;
3993 Set_Msg_Insertion_Unit_Name (Suffix => False);
3994 else
3995 Set_Msg_Insertion_Unit_Name;
3996 end if;
3998 when '{' =>
3999 Set_Msg_Insertion_File_Name;
4001 when '}' =>
4002 Set_Msg_Insertion_Type_Reference (Flag);
4004 when '*' =>
4005 Set_Msg_Insertion_Reserved_Name;
4007 when '&' =>
4008 Set_Msg_Insertion_Node;
4010 when '#' =>
4011 Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag);
4013 when '\' =>
4014 Continuation := True;
4016 if P <= Text'Last and then Text (P) = '\' then
4017 Continuation_New_Line := True;
4018 P := P + 1;
4019 end if;
4021 when '@' =>
4022 Set_Msg_Insertion_Column;
4024 when '>' =>
4025 Set_Msg_Insertion_Run_Time_Name;
4027 when '^' =>
4028 Set_Msg_Insertion_Uint;
4030 when '`' =>
4031 Manual_Quote_Mode := not Manual_Quote_Mode;
4032 Set_Msg_Char ('"');
4034 when '!' =>
4035 null; -- already dealt with
4037 when '?' =>
4038 Skip_Msg_Insertion_Warning ('?');
4040 when '<' =>
4041 Skip_Msg_Insertion_Warning ('<');
4043 when '|' =>
4044 null; -- already dealt with
4046 when ''' =>
4047 Set_Msg_Char (Text (P));
4048 P := P + 1;
4050 when '~' =>
4051 Set_Msg_Str (Error_Msg_String (1 .. Error_Msg_Strlen));
4053 -- Upper case letter
4055 when 'A' .. 'Z' =>
4057 -- Start of reserved word if two or more
4059 if P <= Text'Last and then Text (P) in 'A' .. 'Z' then
4060 P := P - 1;
4061 Set_Msg_Insertion_Reserved_Word (Text, P);
4063 -- Single upper case letter is just inserted
4065 else
4066 Set_Msg_Char (C);
4067 end if;
4069 -- '[' (will be/would have been raised at run time)
4071 when '[' =>
4073 -- Switch the message from a warning to an error if the flag
4074 -- -gnatwE is specified to treat run-time exception warnings
4075 -- as errors.
4077 if Is_Warning_Msg
4078 and then Warning_Mode = Treat_Run_Time_Warnings_As_Errors
4079 then
4080 Is_Warning_Msg := False;
4081 Is_Runtime_Raise := True;
4082 end if;
4084 if Is_Warning_Msg then
4085 Set_Msg_Str ("will be raised at run time");
4086 else
4087 Set_Msg_Str ("would have been raised at run time");
4088 end if;
4090 -- ']' (may be/might have been raised at run time)
4092 when ']' =>
4093 if Is_Warning_Msg then
4094 Set_Msg_Str ("may be raised at run time");
4095 else
4096 Set_Msg_Str ("might have been raised at run time");
4097 end if;
4099 -- Normal character with no special treatment
4101 when others =>
4102 Set_Msg_Char (C);
4103 end case;
4104 end loop;
4105 end Set_Msg_Text;
4107 ----------------
4108 -- Set_Posted --
4109 ----------------
4111 procedure Set_Posted (N : Node_Id) is
4112 P : Node_Id;
4114 begin
4115 if Is_Serious_Error then
4117 -- We always set Error_Posted on the node itself
4119 Set_Error_Posted (N);
4121 -- If it is a subexpression, then set Error_Posted on parents up to
4122 -- and including the first non-subexpression construct. This helps
4123 -- avoid cascaded error messages within a single expression.
4125 P := N;
4126 loop
4127 P := Parent (P);
4128 exit when No (P);
4129 Set_Error_Posted (P);
4130 exit when Nkind (P) not in N_Subexpr;
4131 end loop;
4133 if Nkind (P) in N_Pragma_Argument_Association
4134 | N_Component_Association
4135 | N_Discriminant_Association
4136 | N_Generic_Association
4137 | N_Parameter_Association
4138 then
4139 Set_Error_Posted (Parent (P));
4140 end if;
4142 -- A special check, if we just posted an error on an attribute
4143 -- definition clause, then also set the entity involved as posted.
4144 -- For example, this stops complaining about the alignment after
4145 -- complaining about the size, which is likely to be useless.
4147 if Nkind (P) = N_Attribute_Definition_Clause then
4148 if Is_Entity_Name (Name (P)) then
4149 Set_Error_Posted (Entity (Name (P)));
4150 end if;
4151 end if;
4152 end if;
4153 end Set_Posted;
4155 -----------------------
4156 -- Set_Qualification --
4157 -----------------------
4159 procedure Set_Qualification (N : Nat; E : Entity_Id) is
4160 begin
4161 if N /= 0 and then Scope (E) /= Standard_Standard then
4162 Set_Qualification (N - 1, Scope (E));
4163 Set_Msg_Node (Scope (E));
4164 Set_Msg_Char ('.');
4165 end if;
4166 end Set_Qualification;
4168 ------------------------
4169 -- Special_Msg_Delete --
4170 ------------------------
4172 -- Is it really right to have all this specialized knowledge in errout?
4174 function Special_Msg_Delete
4175 (Msg : String;
4176 N : Node_Or_Entity_Id;
4177 E : Node_Or_Entity_Id) return Boolean
4179 begin
4180 -- Never delete messages in -gnatdO mode
4182 if Debug_Flag_OO then
4183 return False;
4185 -- Processing for "Size too small" messages
4187 elsif Is_Size_Too_Small_Message (Msg) then
4189 -- Suppress "size too small" errors in CodePeer mode, since code may
4190 -- be analyzed in a different configuration than the one used for
4191 -- compilation. Even when the configurations match, this message
4192 -- may be issued on correct code, because pragma Pack is ignored
4193 -- in CodePeer mode.
4195 if CodePeer_Mode then
4196 return True;
4198 -- When a size is wrong for a frozen type there is no explicit size
4199 -- clause, and other errors have occurred, suppress the message,
4200 -- since it is likely that this size error is a cascaded result of
4201 -- other errors. The reason we eliminate unfrozen types is that
4202 -- messages issued before the freeze type are for sure OK.
4204 elsif Nkind (N) in N_Entity
4205 and then Is_Frozen (E)
4206 and then Serious_Errors_Detected > 0
4207 and then Nkind (N) /= N_Component_Clause
4208 and then Nkind (Parent (N)) /= N_Component_Clause
4209 and then
4210 No (Get_Attribute_Definition_Clause (E, Attribute_Size))
4211 and then
4212 No (Get_Attribute_Definition_Clause (E, Attribute_Object_Size))
4213 and then
4214 No (Get_Attribute_Definition_Clause (E, Attribute_Value_Size))
4215 then
4216 return True;
4217 end if;
4218 end if;
4220 -- All special tests complete, so go ahead with message
4222 return False;
4223 end Special_Msg_Delete;
4225 -----------------
4226 -- SPARK_Msg_N --
4227 -----------------
4229 procedure SPARK_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
4230 begin
4231 if SPARK_Mode /= Off then
4232 Error_Msg_N (Msg, N);
4233 end if;
4234 end SPARK_Msg_N;
4236 ------------------
4237 -- SPARK_Msg_NE --
4238 ------------------
4240 procedure SPARK_Msg_NE
4241 (Msg : String;
4242 N : Node_Or_Entity_Id;
4243 E : Node_Or_Entity_Id)
4245 begin
4246 if SPARK_Mode /= Off then
4247 Error_Msg_NE (Msg, N, E);
4248 end if;
4249 end SPARK_Msg_NE;
4251 --------------------------
4252 -- Unwind_Internal_Type --
4253 --------------------------
4255 procedure Unwind_Internal_Type (Ent : in out Entity_Id) is
4256 Derived : Boolean := False;
4257 Mchar : Character;
4258 Old_Ent : Entity_Id;
4260 begin
4261 -- Undo placement of a quote, since we will put it back later
4263 Mchar := Msg_Buffer (Msglen);
4265 if Mchar = '"' then
4266 Msglen := Msglen - 1;
4267 end if;
4269 -- The loop here deals with recursive types, we are trying to find a
4270 -- related entity that is not an implicit type. Note that the check with
4271 -- Old_Ent stops us from getting "stuck". Also, we don't output the
4272 -- "type derived from" message more than once in the case where we climb
4273 -- up multiple levels.
4275 Find : loop
4276 Old_Ent := Ent;
4278 -- Implicit access type, use directly designated type In Ada 2005,
4279 -- the designated type may be an anonymous access to subprogram, in
4280 -- which case we can only point to its definition.
4282 if Is_Access_Type (Ent) then
4283 if Ekind (Ent) = E_Access_Subprogram_Type
4284 or else Ekind (Ent) = E_Anonymous_Access_Subprogram_Type
4285 or else Is_Access_Protected_Subprogram_Type (Ent)
4286 then
4287 Ent := Directly_Designated_Type (Ent);
4289 if not Comes_From_Source (Ent) then
4290 if Buffer_Ends_With ("type ") then
4291 Buffer_Remove ("type ");
4292 end if;
4293 end if;
4295 if Ekind (Ent) = E_Function then
4296 Set_Msg_Str ("access to function ");
4297 elsif Ekind (Ent) = E_Procedure then
4298 Set_Msg_Str ("access to procedure ");
4299 else
4300 Set_Msg_Str ("access to subprogram");
4301 end if;
4303 exit Find;
4305 -- Type is access to object, named or anonymous
4307 else
4308 Set_Msg_Str ("access to ");
4309 Ent := Directly_Designated_Type (Ent);
4310 end if;
4312 -- Classwide type
4314 elsif Is_Class_Wide_Type (Ent) then
4315 Class_Flag := True;
4316 Ent := Root_Type (Ent);
4318 -- Use base type if this is a subtype
4320 elsif Ent /= Base_Type (Ent) then
4321 Buffer_Remove ("type ");
4323 -- Avoid duplication "subtype of subtype of", and also replace
4324 -- "derived from subtype of" simply by "derived from"
4326 if not Buffer_Ends_With ("subtype of ")
4327 and then not Buffer_Ends_With ("derived from ")
4328 then
4329 Set_Msg_Str ("subtype of ");
4330 end if;
4332 Ent := Base_Type (Ent);
4334 -- If this is a base type with a first named subtype, use the first
4335 -- named subtype instead. This is not quite accurate in all cases,
4336 -- but it makes too much noise to be accurate and add 'Base in all
4337 -- cases. Note that we only do this is the first named subtype is not
4338 -- itself an internal name. This avoids the obvious loop (subtype ->
4339 -- basetype -> subtype) which would otherwise occur).
4341 else
4342 declare
4343 FST : constant Entity_Id := First_Subtype (Ent);
4345 begin
4346 if not Is_Internal_Name (Chars (FST)) then
4347 Ent := FST;
4348 exit Find;
4350 -- Otherwise use root type
4352 else
4353 if not Derived then
4354 Buffer_Remove ("type ");
4356 -- Test for "subtype of type derived from" which seems
4357 -- excessive and is replaced by "type derived from".
4359 Buffer_Remove ("subtype of");
4361 -- Avoid duplicated "type derived from type derived from"
4363 if not Buffer_Ends_With ("type derived from ") then
4364 Set_Msg_Str ("type derived from ");
4365 end if;
4367 Derived := True;
4368 end if;
4369 end if;
4370 end;
4372 Ent := Etype (Ent);
4373 end if;
4375 -- If we are stuck in a loop, get out and settle for the internal
4376 -- name after all. In this case we set to kill the message if it is
4377 -- not the first error message (we really try hard not to show the
4378 -- dirty laundry of the implementation to the poor user).
4380 if Ent = Old_Ent then
4381 Kill_Message := True;
4382 exit Find;
4383 end if;
4385 -- Get out if we finally found a non-internal name to use
4387 exit Find when not Is_Internal_Name (Chars (Ent));
4388 end loop Find;
4390 if Mchar = '"' then
4391 Set_Msg_Char ('"');
4392 end if;
4393 end Unwind_Internal_Type;
4395 --------------------
4396 -- Warn_Insertion --
4397 --------------------
4399 function Warn_Insertion return String is
4400 begin
4401 if Warning_Msg_Char = "? " then
4402 return "??";
4403 elsif Warning_Msg_Char = " " then
4404 return "?";
4405 elsif Warning_Msg_Char (2) = ' ' then
4406 return '?' & Warning_Msg_Char (1) & '?';
4407 else
4408 return '?' & Warning_Msg_Char & '?';
4409 end if;
4410 end Warn_Insertion;
4412 end Errout;