RISC-V/libgcc: Save/Restore routines for E goes with ABI.
[official-gcc.git] / gcc / ada / errout.adb
blobf4660c4e35c9f385443e3632e216c5128632bfe9
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-2024, 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 Diagnostics.Converter; use Diagnostics.Converter;
37 with Einfo; use Einfo;
38 with Einfo.Entities; use Einfo.Entities;
39 with Einfo.Utils; use Einfo.Utils;
40 with Erroutc; use Erroutc;
41 with Gnatvsn; use Gnatvsn;
42 with Lib; use Lib;
43 with Opt; use Opt;
44 with Nlists; use Nlists;
45 with Output; use Output;
46 with Scans; use Scans;
47 with Sem_Aux; use Sem_Aux;
48 with Sinput; use Sinput;
49 with Sinfo; use Sinfo;
50 with Sinfo.Nodes; use Sinfo.Nodes;
51 with Sinfo.Utils; use Sinfo.Utils;
52 with Snames; use Snames;
53 with Stand; use Stand;
54 with Stringt; use Stringt;
55 with Stylesw; use Stylesw;
56 with System.OS_Lib;
57 with Uname; use Uname;
58 with Warnsw;
60 package body Errout is
62 Errors_Must_Be_Ignored : Boolean := False;
63 -- Set to True by procedure Set_Ignore_Errors (True), when calls to error
64 -- message procedures should be ignored (when parsing irrelevant text in
65 -- sources being preprocessed).
67 Finalize_Called : Boolean := False;
68 -- Set True if the Finalize routine has been called
70 Warn_On_Instance : Boolean;
71 -- Flag set true for warning message to be posted on instance
73 ------------------------------------
74 -- Table of Non-Instance Messages --
75 ------------------------------------
77 -- This table contains an entry for every error message processed by the
78 -- Error_Msg routine that is not posted on generic (or inlined) instance.
79 -- As explained in further detail in the Error_Msg procedure body, this
80 -- table is used to avoid posting redundant messages on instances.
82 type NIM_Record is record
83 Msg : String_Ptr;
84 Loc : Source_Ptr;
85 end record;
86 -- Type used to store text and location of one message
88 package Non_Instance_Msgs is new Table.Table (
89 Table_Component_Type => NIM_Record,
90 Table_Index_Type => Int,
91 Table_Low_Bound => 1,
92 Table_Initial => 100,
93 Table_Increment => 100,
94 Table_Name => "Non_Instance_Msgs");
96 -----------------------
97 -- Local Subprograms --
98 -----------------------
100 procedure Error_Msg_Internal
101 (Msg : String;
102 Span : Source_Span;
103 Opan : Source_Span;
104 Msg_Cont : Boolean);
105 -- This is the low-level routine used to post messages after dealing with
106 -- the issue of messages placed on instantiations (which get broken up
107 -- into separate calls in Error_Msg). Span is the location on which the
108 -- flag will be placed in the output. In the case where the flag is on
109 -- the template, this points directly to the template, not to one of the
110 -- instantiation copies of the template. Opan is the original location
111 -- used to flag the error, and this may indeed point to an instantiation
112 -- copy. So typically we can see Opan pointing to the template location
113 -- in an instantiation copy when Span points to the source location of
114 -- the actual instantiation (i.e the line with the new). Msg_Cont is
115 -- set true if this is a continuation message.
117 function No_Warnings (N : Node_Or_Entity_Id) return Boolean;
118 -- Determines if warnings should be suppressed for the given node
120 function OK_Node (N : Node_Id) return Boolean;
121 -- Determines if a node is an OK node to place an error message on (return
122 -- True) or if the error message should be suppressed (return False). A
123 -- message is suppressed if the node already has an error posted on it,
124 -- or if it refers to an Etype that has an error posted on it, or if
125 -- it references an Entity that has an error posted on it.
127 procedure Output_JSON_Message (Error_Id : Error_Msg_Id);
128 -- Output error message Error_Id and any subsequent continuation message
129 -- using a JSON format similar to the one GCC uses when passed
130 -- -fdiagnostics-format=json.
132 procedure Output_Source_Line
133 (L : Physical_Line_Number;
134 Sfile : Source_File_Index;
135 Errs : Boolean);
136 -- Outputs text of source line L, in file S, together with preceding line
137 -- number, as described above for Output_Line_Number. The Errs parameter
138 -- indicates if there are errors attached to the line, which forces
139 -- listing on, even in the presence of pragma List (Off).
141 function Paren_Required (N : Node_Id) return Boolean;
142 -- Subsidiary to First_Sloc and Last_Sloc. Returns True iff parentheses
143 -- around node N are required by the Ada syntax, e.g. when N is an
144 -- expression of a qualified expression.
146 procedure Set_Msg_Insertion_Column;
147 -- Handle column number insertion (@ insertion character)
149 procedure Set_Msg_Insertion_Node;
150 -- Handle node (name from node) insertion (& insertion character)
152 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr);
153 -- Handle type reference (right brace insertion character). Flag is the
154 -- location of the flag, which is provided for the internal call to
155 -- Set_Msg_Insertion_Line_Number,
157 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True);
158 -- Handle unit name insertion ($ insertion character). Depending on Boolean
159 -- parameter Suffix, (spec) or (body) is appended after the unit name.
161 procedure Set_Msg_Node (Node : Node_Id);
162 -- Add the sequence of characters for the name associated with the given
163 -- node to the current message. For N_Designator, N_Selected_Component,
164 -- N_Defining_Program_Unit_Name, and N_Expanded_Name, the Prefix is
165 -- included as well.
167 procedure Set_Posted (N : Node_Id);
168 -- Sets the Error_Posted flag on the given node, and all its parents that
169 -- are subexpressions and then on the parent non-subexpression construct
170 -- that contains the original expression. If that parent is a named
171 -- association, the flag is further propagated to its parent. This is done
172 -- in order to guard against cascaded errors. Note that this call has an
173 -- effect for a serious error only.
175 procedure Set_Qualification (N : Nat; E : Entity_Id);
176 -- Outputs up to N levels of qualification for the given entity. For
177 -- example, the entity A.B.C.D will output B.C. if N = 2.
179 function Should_Ignore_Pragma_SPARK_Mode return Boolean;
180 -- Return whether pragma Ignore_Pragma (SPARK_Mode) was specified. This is
181 -- similar to Sem_Util.Should_Ignore_Pragma_Par but located here to avoid
182 -- problematic dependency on Sem_Util.
184 function Special_Msg_Delete
185 (Msg : String;
186 N : Node_Or_Entity_Id;
187 E : Node_Or_Entity_Id) return Boolean;
188 -- This function is called from Error_Msg_NEL, passing the message Msg,
189 -- node N on which the error is to be posted, and the entity or node E
190 -- to be used for an & insertion in the message if any. The job of this
191 -- procedure is to test for certain cascaded messages that we would like
192 -- to suppress. If the message is to be suppressed then we return True.
193 -- If the message should be generated (the normal case) False is returned.
195 procedure Unwind_Internal_Type (Ent : in out Entity_Id);
196 -- This procedure is given an entity id for an internal type, i.e. a type
197 -- with an internal name. It unwinds the type to try to get to something
198 -- reasonably printable, generating prefixes like "subtype of", "access
199 -- to", etc along the way in the buffer. The value in Ent on return is the
200 -- final name to be printed. Hopefully this is not an internal name, but in
201 -- some internal name cases, it is an internal name, and has to be printed
202 -- anyway (although in this case the message has been killed if possible).
203 -- The global variable Class_Flag is set to True if the resulting entity
204 -- should have 'Class appended to its name (see Add_Class procedure), and
205 -- is otherwise unchanged.
207 procedure Validate_Specific_Warnings;
208 -- Checks that specific warnings are consistent (for non-configuration
209 -- case, properly closed, and used).
211 function Warn_Insertion return String;
212 -- This is called for warning messages only (so Warning_Msg_Char is set)
213 -- and returns a corresponding string to use at the beginning of generated
214 -- auxiliary messages, such as "in instantiation at ...".
215 -- "?" returns "??"
216 -- " " returns "?"
217 -- other trimmed, prefixed and suffixed with "?".
219 -----------------------
220 -- Change_Error_Text --
221 -----------------------
223 procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String) is
224 Save_Next : Error_Msg_Id;
225 Err_Id : Error_Msg_Id := Error_Id;
227 begin
228 Set_Msg_Text (New_Msg, Errors.Table (Error_Id).Sptr.Ptr);
229 Errors.Table (Error_Id).Text := new String'(Msg_Buffer (1 .. Msglen));
231 -- If in immediate error message mode, output modified error message now
232 -- This is just a bit tricky, because we want to output just a single
233 -- message, and the messages we modified is already linked in. We solve
234 -- this by temporarily resetting its forward pointer to empty.
236 if Debug_Flag_OO then
237 Save_Next := Errors.Table (Error_Id).Next;
238 Errors.Table (Error_Id).Next := No_Error_Msg;
239 Write_Eol;
240 Output_Source_Line
241 (Errors.Table (Error_Id).Line, Errors.Table (Error_Id).Sfile, True);
242 Output_Error_Msgs (Err_Id);
243 Errors.Table (Error_Id).Next := Save_Next;
244 end if;
245 end Change_Error_Text;
247 ------------------------
248 -- Compilation_Errors --
249 ------------------------
251 function Compilation_Errors return Boolean is
252 begin
253 if not Finalize_Called then
254 raise Program_Error;
255 else
256 return Erroutc.Compilation_Errors;
257 end if;
258 end Compilation_Errors;
260 --------------------------------------
261 -- Delete_Warning_And_Continuations --
262 --------------------------------------
264 procedure Delete_Warning_And_Continuations (Msg : Error_Msg_Id) is
265 Id : Error_Msg_Id;
267 begin
268 pragma Assert (not Errors.Table (Msg).Msg_Cont);
270 Id := Msg;
271 loop
272 declare
273 M : Error_Msg_Object renames Errors.Table (Id);
275 begin
276 if not M.Deleted then
277 M.Deleted := True;
278 Warnings_Detected := Warnings_Detected - 1;
280 if M.Warn_Err then
281 Warnings_Treated_As_Errors := Warnings_Treated_As_Errors - 1;
282 end if;
283 end if;
285 Id := M.Next;
286 exit when Id = No_Error_Msg;
287 exit when not Errors.Table (Id).Msg_Cont;
288 end;
289 end loop;
290 end Delete_Warning_And_Continuations;
292 ---------------
293 -- Error_Msg --
294 ---------------
296 -- Error_Msg posts a flag at the given location, except that if the
297 -- Flag_Location/Flag_Span points within a generic template and corresponds
298 -- to an instantiation of this generic template, then the actual message
299 -- will be posted on the generic instantiation, along with additional
300 -- messages referencing the generic declaration.
302 procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
303 begin
304 Error_Msg (Msg, To_Span (Flag_Location), Current_Node);
305 end Error_Msg;
307 procedure Error_Msg (Msg : String; Flag_Span : Source_Span) is
308 begin
309 Error_Msg (Msg, Flag_Span, Current_Node);
310 end Error_Msg;
312 procedure Error_Msg
313 (Msg : String;
314 Flag_Location : Source_Ptr;
315 N : Node_Id;
316 Is_Compile_Time_Pragma : Boolean)
318 Save_Is_Compile_Time_Msg : constant Boolean := Is_Compile_Time_Msg;
319 begin
320 Is_Compile_Time_Msg := Is_Compile_Time_Pragma;
321 Error_Msg (Msg, To_Span (Flag_Location), N);
322 Is_Compile_Time_Msg := Save_Is_Compile_Time_Msg;
323 end Error_Msg;
325 procedure Error_Msg
326 (Msg : String;
327 Flag_Location : Source_Ptr;
328 N : Node_Id)
330 begin
331 Error_Msg (Msg, To_Span (Flag_Location), N);
332 end Error_Msg;
334 procedure Error_Msg
335 (Msg : String;
336 Flag_Span : Source_Span;
337 N : Node_Id)
339 Flag_Location : constant Source_Ptr := Flag_Span.Ptr;
341 Sindex : Source_File_Index;
342 -- Source index for flag location
344 Orig_Loc : Source_Ptr;
345 -- Original location of Flag_Location (i.e. location in original
346 -- template in instantiation case, otherwise unchanged).
348 begin
349 -- Return if all errors are to be ignored
351 if Get_Ignore_Errors then
352 return;
353 end if;
355 -- If we already have messages, and we are trying to place a message at
356 -- No_Location, then just ignore the attempt since we assume that what
357 -- is happening is some cascaded junk. Note that this is safe in the
358 -- sense that proceeding will surely bomb. We will also bomb if the flag
359 -- location is No_Location and we don't have any messages so far, but
360 -- that is a real bug and a legitimate bomb, so we go ahead.
362 if Flag_Location = No_Location
363 and then Total_Errors_Detected > 0
364 then
365 return;
366 end if;
368 -- Start of processing for new message
370 Sindex := Get_Source_File_Index (Flag_Location);
371 Prescan_Message (Msg);
372 Orig_Loc := Original_Location (Flag_Location);
374 -- If the current location is in an instantiation, the issue arises of
375 -- whether to post the message on the template or the instantiation.
377 -- The way we decide is to see if we have posted the same message on
378 -- the template when we compiled the template (the template is always
379 -- compiled before any instantiations). For this purpose, we use a
380 -- separate table of messages. The reason we do this is twofold:
382 -- First, the messages can get changed by various processing
383 -- including the insertion of tokens etc, making it hard to
384 -- do the comparison.
386 -- Second, we will suppress a warning on a template if it is not in
387 -- the current extended source unit. That's reasonable and means we
388 -- don't want the warning on the instantiation here either, but it
389 -- does mean that the main error table would not in any case include
390 -- the message.
392 if Flag_Location = Orig_Loc then
393 Non_Instance_Msgs.Append ((new String'(Msg), Flag_Location));
394 Warn_On_Instance := False;
396 -- Here we have an instance message
398 else
399 -- Delete if debug flag off, and this message duplicates a message
400 -- already posted on the corresponding template
402 if not Debug_Flag_GG then
403 for J in Non_Instance_Msgs.First .. Non_Instance_Msgs.Last loop
404 if Msg = Non_Instance_Msgs.Table (J).Msg.all
405 and then Non_Instance_Msgs.Table (J).Loc = Orig_Loc
406 then
407 return;
408 end if;
409 end loop;
410 end if;
412 -- No duplicate, so error/warning will be posted on instance
414 Warn_On_Instance := Is_Warning_Msg;
415 end if;
417 -- Ignore warning message that is suppressed for this location. Note
418 -- that style checks are not considered warning messages for this
419 -- purpose.
421 if Is_Warning_Msg
422 and then Warnings_Suppressed (Orig_Loc) /= No_String
423 then
424 return;
426 -- For style messages, check too many messages so far
428 elsif Is_Style_Msg
429 and then Maximum_Messages /= 0
430 and then Warnings_Detected >= Maximum_Messages
431 then
432 return;
434 -- Suppress warnings inside a loop that is known to be null or is
435 -- probably null (i.e. when loop executes only if invalid values
436 -- present). In either case warnings in the loop are likely to be junk.
438 elsif Is_Warning_Msg and then Present (N) then
440 declare
441 P : Node_Id;
443 begin
444 P := Parent (N);
445 while Present (P) loop
446 if Nkind (P) = N_Loop_Statement
447 and then Suppress_Loop_Warnings (P)
448 then
449 return;
450 end if;
452 P := Parent (P);
453 end loop;
454 end;
455 end if;
457 -- The idea at this stage is that we have two kinds of messages
459 -- First, we have those messages that are to be placed as requested at
460 -- Flag_Location. This includes messages that have nothing to do with
461 -- generics, and also messages placed on generic templates that reflect
462 -- an error in the template itself. For such messages we simply call
463 -- Error_Msg_Internal to place the message in the requested location.
465 if Instantiation (Sindex) = No_Location then
466 Error_Msg_Internal (Msg, Flag_Span, Flag_Span, False);
467 return;
468 end if;
470 -- If we are trying to flag an error in an instantiation, we may have
471 -- a generic contract violation. What we generate in this case is:
473 -- instantiation error at ...
474 -- original error message
476 -- or
478 -- warning: in instantiation at ...
479 -- warning: original warning message
481 -- or
483 -- info: in instantiation at ...
484 -- info: original info message
486 -- All these messages are posted at the location of the top level
487 -- instantiation. If there are nested instantiations, then the
488 -- instantiation error message can be repeated, pointing to each
489 -- of the relevant instantiations.
491 -- Note: the instantiation mechanism is also shared for inlining of
492 -- subprogram bodies when front end inlining is done. In this case the
493 -- messages have the form:
495 -- in inlined body at ...
496 -- original error message
498 -- or
500 -- warning: in inlined body at ...
501 -- warning: original warning message
503 -- or
505 -- info: in inlined body at ...
506 -- info: original info message
508 -- OK, here we have an instantiation error, and we need to generate the
509 -- error on the instantiation, rather than on the template.
511 declare
512 Actual_Error_Loc : Source_Ptr;
513 -- Location of outer level instantiation in instantiation case, or
514 -- just a copy of Flag_Location in the normal case. This is the
515 -- location where all error messages will actually be posted.
517 Save_Error_Msg_Sloc : constant Source_Ptr := Error_Msg_Sloc;
518 -- Save possible location set for caller's message. We need to use
519 -- Error_Msg_Sloc for the location of the instantiation error but we
520 -- have to preserve a possible original value.
522 X : Source_File_Index;
524 Msg_Cont_Status : Boolean;
525 -- Used to label continuation lines in instantiation case with
526 -- proper Msg_Cont status.
528 begin
529 -- Loop to find highest level instantiation, where all error
530 -- messages will be placed.
532 X := Sindex;
533 loop
534 Actual_Error_Loc := Instantiation (X);
535 X := Get_Source_File_Index (Actual_Error_Loc);
536 exit when Instantiation (X) = No_Location;
537 end loop;
539 -- Since we are generating the messages at the instantiation point in
540 -- any case, we do not want the references to the bad lines in the
541 -- instance to be annotated with the location of the instantiation.
543 Suppress_Instance_Location := True;
544 Msg_Cont_Status := False;
546 -- Loop to generate instantiation messages
548 Error_Msg_Sloc := Flag_Location;
549 X := Get_Source_File_Index (Flag_Location);
550 while Instantiation (X) /= No_Location loop
552 -- Suppress instantiation message on continuation lines
554 if Msg (Msg'First) /= '\' then
556 -- Case of inlined body
558 if Inlined_Body (X) then
559 if Is_Info_Msg then
560 Error_Msg_Internal
561 (Msg => "info: in inlined body #",
562 Span => To_Span (Actual_Error_Loc),
563 Opan => Flag_Span,
564 Msg_Cont => Msg_Cont_Status);
566 elsif Is_Warning_Msg then
567 Error_Msg_Internal
568 (Msg => Warn_Insertion & "in inlined body #",
569 Span => To_Span (Actual_Error_Loc),
570 Opan => Flag_Span,
571 Msg_Cont => Msg_Cont_Status);
573 elsif Is_Style_Msg then
574 Error_Msg_Internal
575 (Msg => "style: in inlined body #",
576 Span => To_Span (Actual_Error_Loc),
577 Opan => Flag_Span,
578 Msg_Cont => Msg_Cont_Status);
580 else
581 Error_Msg_Internal
582 (Msg => "error in inlined body #",
583 Span => To_Span (Actual_Error_Loc),
584 Opan => Flag_Span,
585 Msg_Cont => Msg_Cont_Status);
586 end if;
588 -- Case of generic instantiation
590 else
591 if Is_Info_Msg then
592 Error_Msg_Internal
593 (Msg => "info: in instantiation #",
594 Span => To_Span (Actual_Error_Loc),
595 Opan => Flag_Span,
596 Msg_Cont => Msg_Cont_Status);
598 elsif Is_Warning_Msg then
599 Error_Msg_Internal
600 (Msg => Warn_Insertion & "in instantiation #",
601 Span => To_Span (Actual_Error_Loc),
602 Opan => Flag_Span,
603 Msg_Cont => Msg_Cont_Status);
605 elsif Is_Style_Msg then
606 Error_Msg_Internal
607 (Msg => "style: in instantiation #",
608 Span => To_Span (Actual_Error_Loc),
609 Opan => Flag_Span,
610 Msg_Cont => Msg_Cont_Status);
612 else
613 Error_Msg_Internal
614 (Msg => "instantiation error #",
615 Span => To_Span (Actual_Error_Loc),
616 Opan => Flag_Span,
617 Msg_Cont => Msg_Cont_Status);
618 end if;
619 end if;
620 end if;
622 Error_Msg_Sloc := Instantiation (X);
623 X := Get_Source_File_Index (Error_Msg_Sloc);
624 Msg_Cont_Status := True;
625 end loop;
627 Suppress_Instance_Location := False;
628 Error_Msg_Sloc := Save_Error_Msg_Sloc;
630 -- Here we output the original message on the outer instantiation
632 Error_Msg_Internal
633 (Msg => Msg,
634 Span => To_Span (Actual_Error_Loc),
635 Opan => Flag_Span,
636 Msg_Cont => Msg_Cont_Status);
637 end;
638 end Error_Msg;
640 ----------------------------------
641 -- Error_Msg_Ada_2005_Extension --
642 ----------------------------------
644 procedure Error_Msg_Ada_2005_Extension (Extension : String) is
645 Loc : constant Source_Ptr := Token_Ptr;
646 begin
647 if Ada_Version < Ada_2005 then
648 Error_Msg (Extension & " is an Ada 2005 extension", Loc);
650 if No (Ada_Version_Pragma) then
651 Error_Msg ("\unit must be compiled with -gnat05 switch", Loc);
652 else
653 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
654 Error_Msg ("\incompatible with Ada version set#", Loc);
655 end if;
656 end if;
657 end Error_Msg_Ada_2005_Extension;
659 --------------------------------
660 -- Error_Msg_Ada_2012_Feature --
661 --------------------------------
663 procedure Error_Msg_Ada_2012_Feature (Feature : String; Loc : Source_Ptr) is
664 begin
665 if Ada_Version < Ada_2012 then
666 Error_Msg (Feature & " is an Ada 2012 feature", Loc);
668 if No (Ada_Version_Pragma) then
669 Error_Msg ("\unit must be compiled with -gnat2012 switch", Loc);
670 else
671 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
672 Error_Msg ("\incompatible with Ada version set#", Loc);
673 end if;
674 end if;
675 end Error_Msg_Ada_2012_Feature;
677 --------------------------------
678 -- Error_Msg_Ada_2022_Feature --
679 --------------------------------
681 procedure Error_Msg_Ada_2022_Feature (Feature : String; Loc : Source_Ptr) is
682 begin
683 if Ada_Version < Ada_2022 then
684 Error_Msg (Feature & " is an Ada 2022 feature", Loc);
686 if No (Ada_Version_Pragma) then
687 Error_Msg ("\unit must be compiled with -gnat2022 switch", Loc);
688 else
689 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
690 Error_Msg ("\incompatible with Ada version set#", Loc);
691 end if;
692 end if;
693 end Error_Msg_Ada_2022_Feature;
695 ------------------
696 -- Error_Msg_AP --
697 ------------------
699 procedure Error_Msg_AP (Msg : String) is
700 S1 : Source_Ptr;
701 C : Character;
703 begin
704 -- If we had saved the Scan_Ptr value after scanning the previous
705 -- token, then we would have exactly the right place for putting
706 -- the flag immediately at hand. However, that would add at least
707 -- two instructions to a Scan call *just* to service the possibility
708 -- of an Error_Msg_AP call. So instead we reconstruct that value.
710 -- We have two possibilities, start with Prev_Token_Ptr and skip over
711 -- the current token, which is made harder by the possibility that this
712 -- token may be in error, or start with Token_Ptr and work backwards.
713 -- We used to take the second approach, but it's hard because of
714 -- comments, and harder still because things that look like comments
715 -- can appear inside strings. So now we take the first approach.
717 -- Note: in the case where there is no previous token, Prev_Token_Ptr
718 -- is set to Source_First, which is a reasonable position for the
719 -- error flag in this situation.
721 S1 := Prev_Token_Ptr;
722 C := Source (S1);
724 -- If the previous token is a string literal, we need a special approach
725 -- since there may be white space inside the literal and we don't want
726 -- to stop on that white space.
728 -- Note: since this is an error recovery issue anyway, it is not worth
729 -- worrying about special UTF_32 line terminator characters here.
731 if Prev_Token = Tok_String_Literal then
732 loop
733 S1 := S1 + 1;
735 if Source (S1) = C then
736 S1 := S1 + 1;
737 exit when Source (S1) /= C;
738 elsif Source (S1) in Line_Terminator then
739 exit;
740 end if;
741 end loop;
743 -- Character literal also needs special handling
745 elsif Prev_Token = Tok_Char_Literal then
746 S1 := S1 + 3;
748 -- Otherwise we search forward for the end of the current token, marked
749 -- by a line terminator, white space, a comment symbol or if we bump
750 -- into the following token (i.e. the current token).
752 -- Again, it is not worth worrying about UTF_32 special line terminator
753 -- characters in this context, since this is only for error recovery.
755 else
756 while Source (S1) not in Line_Terminator
757 and then Source (S1) /= ' '
758 and then Source (S1) /= ASCII.HT
759 and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-')
760 and then S1 /= Token_Ptr
761 loop
762 S1 := S1 + 1;
763 end loop;
764 end if;
766 -- S1 is now set to the location for the flag
768 Error_Msg (Msg, S1);
769 end Error_Msg_AP;
771 ------------------
772 -- Error_Msg_BC --
773 ------------------
775 procedure Error_Msg_BC (Msg : String) is
776 begin
777 -- If we are at end of file, post the flag after the previous token
779 if Token = Tok_EOF then
780 Error_Msg_AP (Msg);
782 -- If we are at start of file, post the flag at the current token
784 elsif Token_Ptr = Source_First (Current_Source_File) then
785 Error_Msg_SC (Msg);
787 -- If the character before the current token is a space or a horizontal
788 -- tab, then we place the flag on this character (in the case of a tab
789 -- we would really like to place it in the "last" character of the tab
790 -- space, but that it too much trouble to worry about).
792 elsif Source (Token_Ptr - 1) = ' '
793 or else Source (Token_Ptr - 1) = ASCII.HT
794 then
795 Error_Msg (Msg, Token_Ptr - 1);
797 -- If there is no space or tab before the current token, then there is
798 -- no room to place the flag before the token, so we place it on the
799 -- token instead (this happens for example at the start of a line).
801 else
802 Error_Msg (Msg, Token_Ptr);
803 end if;
804 end Error_Msg_BC;
806 -------------------
807 -- Error_Msg_CRT --
808 -------------------
810 procedure Error_Msg_CRT (Feature : String; N : Node_Id) is
811 begin
812 if No_Run_Time_Mode then
813 Error_Msg_N ('|' & Feature & " not allowed in no run time mode", N);
815 else pragma Assert (Configurable_Run_Time_Mode);
816 Error_Msg_N ('|' & Feature & " not supported by configuration>", N);
817 end if;
819 Configurable_Run_Time_Violations := Configurable_Run_Time_Violations + 1;
820 end Error_Msg_CRT;
822 ------------------
823 -- Error_Msg_PT --
824 ------------------
826 procedure Error_Msg_PT (E : Entity_Id; Iface_Prim : Entity_Id) is
827 begin
828 Error_Msg_N
829 ("illegal overriding of subprogram inherited from interface", E);
831 Error_Msg_Sloc := Sloc (Iface_Prim);
833 if Ekind (E) = E_Function then
834 Error_Msg_N
835 ("\first formal of & declared # must be of mode `IN` "
836 & "or access-to-constant", E);
837 else
838 Error_Msg_N
839 ("\first formal of & declared # must be of mode `OUT`, `IN OUT` "
840 & "or access-to-variable", E);
841 end if;
842 end Error_Msg_PT;
844 -----------------
845 -- Error_Msg_F --
846 -----------------
848 procedure Error_Msg_F (Msg : String; N : Node_Id) is
849 Fst, Lst : Node_Id;
850 begin
851 First_And_Last_Nodes (N, Fst, Lst);
852 Error_Msg_NEL (Msg, N, N,
853 To_Span (Ptr => Sloc (Fst),
854 First => First_Sloc (Fst),
855 Last => Last_Sloc (Lst)));
856 end Error_Msg_F;
858 ------------------
859 -- Error_Msg_FE --
860 ------------------
862 procedure Error_Msg_FE
863 (Msg : String;
864 N : Node_Id;
865 E : Node_Or_Entity_Id)
867 Fst, Lst : Node_Id;
868 begin
869 First_And_Last_Nodes (N, Fst, Lst);
870 Error_Msg_NEL (Msg, N, E,
871 To_Span (Ptr => Sloc (Fst),
872 First => First_Sloc (Fst),
873 Last => Last_Sloc (Lst)));
874 end Error_Msg_FE;
876 ------------------------------
877 -- Error_Msg_GNAT_Extension --
878 ------------------------------
880 procedure Error_Msg_GNAT_Extension
881 (Extension : String;
882 Loc : Source_Ptr;
883 Is_Core_Extension : Boolean := False)
885 begin
886 if (if Is_Core_Extension
887 then Core_Extensions_Allowed
888 else All_Extensions_Allowed)
889 then
890 return;
891 end if;
893 Error_Msg (Extension & " is a 'G'N'A'T-specific extension", Loc);
895 if No (Ada_Version_Pragma) then
896 if Is_Core_Extension then
897 Error_Msg
898 ("\unit must be compiled with -gnatX '[or -gnatX0'] " &
899 "or use pragma Extensions_Allowed (On) '[or All_Extensions']",
900 Loc);
901 else
902 Error_Msg
903 ("\unit must be compiled with -gnatX0 " &
904 "or use pragma Extensions_Allowed (All_Extensions)", Loc);
905 end if;
906 else
907 Error_Msg_Sloc := Sloc (Ada_Version_Pragma);
908 Error_Msg ("\incompatible with Ada version set#", Loc);
909 if Is_Core_Extension then
910 Error_Msg
911 ("\must use pragma Extensions_Allowed (On)" &
912 " '[or All_Extensions']", Loc);
913 else
914 Error_Msg
915 ("\must use pragma Extensions_Allowed (All_Extensions)", Loc);
916 end if;
917 end if;
918 end Error_Msg_GNAT_Extension;
920 ------------------------
921 -- Error_Msg_Internal --
922 ------------------------
924 procedure Error_Msg_Internal
925 (Msg : String;
926 Span : Source_Span;
927 Opan : Source_Span;
928 Msg_Cont : Boolean)
930 Sptr : constant Source_Ptr := Span.Ptr;
931 Optr : constant Source_Ptr := Opan.Ptr;
933 Next_Msg : Error_Msg_Id;
934 -- Pointer to next message at insertion point
936 Prev_Msg : Error_Msg_Id;
937 -- Pointer to previous message at insertion point
939 Temp_Msg : Error_Msg_Id;
941 Warn_Err : Boolean;
942 -- Set if warning to be treated as error
944 procedure Handle_Serious_Error;
945 -- Internal procedure to do all error message handling for a serious
946 -- error message, other than bumping the error counts and arranging
947 -- for the message to be output.
949 --------------------------
950 -- Handle_Serious_Error --
951 --------------------------
953 procedure Handle_Serious_Error is
954 begin
955 -- Turn off code generation if not done already
957 if Operating_Mode = Generate_Code then
958 Operating_Mode := Check_Semantics;
959 Expander_Active := False;
960 end if;
962 -- Set the fatal error flag in the unit table unless we are in
963 -- Try_Semantics mode (in which case we set ignored mode if not
964 -- currently set. This stops the semantics from being performed
965 -- if we find a serious error. This is skipped if we are currently
966 -- dealing with the configuration pragma file.
968 if Current_Source_Unit /= No_Unit then
969 declare
970 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
971 begin
972 if Try_Semantics then
973 if Fatal_Error (U) = None then
974 Set_Fatal_Error (U, Error_Ignored);
975 end if;
976 else
977 Set_Fatal_Error (U, Error_Detected);
978 end if;
979 end;
980 end if;
982 -- Disable warnings on unused use clauses and the like. Otherwise, an
983 -- error might hide a reference to an entity in a used package, so
984 -- after fixing the error, the use clause no longer looks like it was
985 -- unused.
987 Warnsw.Check_Unreferenced := False;
988 Warnsw.Check_Unreferenced_Formals := False;
989 end Handle_Serious_Error;
991 -- Start of processing for Error_Msg_Internal
993 begin
994 -- Detect common mistake of prefixing or suffixing the message with a
995 -- space character.
997 pragma Assert (Msg (Msg'First) /= ' ' and then Msg (Msg'Last) /= ' ');
999 if Raise_Exception_On_Error /= 0 then
1000 raise Error_Msg_Exception;
1001 end if;
1003 Continuation := Msg_Cont;
1004 Continuation_New_Line := False;
1005 Suppress_Message := False;
1006 Kill_Message := False;
1007 Set_Msg_Text (Msg, Sptr);
1009 -- Kill continuation if parent message killed
1011 if Continuation and Last_Killed then
1012 return;
1013 end if;
1015 -- Return without doing anything if message is suppressed
1017 if Suppress_Message
1018 and then not All_Errors_Mode
1019 and then not Is_Warning_Msg
1020 and then not Is_Unconditional_Msg
1021 then
1022 if not Continuation then
1023 Last_Killed := True;
1024 end if;
1026 return;
1027 end if;
1029 -- Return without doing anything if message is killed and this is not
1030 -- the first error message. The philosophy is that if we get a weird
1031 -- error message and we already have had a message, then we hope the
1032 -- weird message is a junk cascaded message
1034 if Kill_Message
1035 and then not All_Errors_Mode
1036 and then Total_Errors_Detected /= 0
1037 then
1038 if not Continuation then
1039 Last_Killed := True;
1040 end if;
1042 return;
1043 end if;
1045 if Is_Info_Msg then
1047 -- Immediate return if info messages are suppressed
1049 if Info_Suppressed then
1050 Cur_Msg := No_Error_Msg;
1051 return;
1052 end if;
1054 -- If the flag location is in the main extended source unit then for
1055 -- sure we want the message since it definitely belongs.
1057 if In_Extended_Main_Source_Unit (Sptr) then
1058 null;
1060 -- Keep info message if message text contains !!
1062 elsif Has_Double_Exclam then
1063 null;
1065 -- Here is where we delete a message from a with'ed unit
1067 else
1068 Cur_Msg := No_Error_Msg;
1070 if not Continuation then
1071 Last_Killed := True;
1072 end if;
1074 return;
1075 end if;
1077 end if;
1079 -- Special check for warning message to see if it should be output
1081 if Is_Warning_Msg then
1083 -- Immediate return if warning message and warnings are suppressed
1085 if Warnings_Suppressed (Optr) /= No_String
1086 or else
1087 Warnings_Suppressed (Sptr) /= No_String
1088 then
1089 Cur_Msg := No_Error_Msg;
1090 return;
1091 end if;
1093 -- If the flag location is in the main extended source unit then for
1094 -- sure we want the warning since it definitely belongs.
1096 if In_Extended_Main_Source_Unit (Sptr) then
1097 null;
1099 -- If the main unit has not been read yet. The warning must be on
1100 -- a configuration file: gnat.adc or user-defined. This means we
1101 -- are not parsing the main unit yet, so skip following checks.
1103 elsif No (Cunit (Main_Unit)) then
1104 null;
1106 -- If the flag location is not in the extended main source unit, then
1107 -- we want to eliminate the warning, unless it is in the extended
1108 -- main code unit and we want warnings on the instance.
1110 elsif In_Extended_Main_Code_Unit (Sptr) and then Warn_On_Instance then
1111 null;
1113 -- Keep warning if debug flag G set
1115 elsif Debug_Flag_GG then
1116 null;
1118 -- Keep warning if message text contains !!
1120 elsif Has_Double_Exclam then
1121 null;
1123 -- Here is where we delete a warning from a with'ed unit
1125 else
1126 Cur_Msg := No_Error_Msg;
1128 if not Continuation then
1129 Last_Killed := True;
1130 end if;
1132 return;
1133 end if;
1134 end if;
1136 -- If message is to be ignored in special ignore message mode, this is
1137 -- where we do this special processing, bypassing message output.
1139 if Ignore_Errors_Enable > 0 then
1140 if Is_Serious_Error then
1141 Handle_Serious_Error;
1142 end if;
1144 return;
1145 end if;
1147 -- If error message line length set, and this is a continuation message
1148 -- then all we do is to append the text to the text of the last message
1149 -- with a comma space separator (eliminating a possible (style) or
1150 -- info prefix).
1152 if Error_Msg_Line_Length /= 0 and then Continuation then
1153 Cur_Msg := Errors.Last;
1155 declare
1156 Oldm : String_Ptr := Errors.Table (Cur_Msg).Text;
1157 Newm : String (1 .. Oldm'Last + 2 + Msglen);
1158 Newl : Natural;
1159 M : Natural;
1161 begin
1162 -- First copy old message to new one and free it
1164 Newm (Oldm'Range) := Oldm.all;
1165 Newl := Oldm'Length;
1166 Free (Oldm);
1168 -- Remove (style) or info: at start of message
1170 if Msglen > 8 and then Msg_Buffer (1 .. 8) = "(style) " then
1171 M := 9;
1173 elsif Msglen > 6 and then Msg_Buffer (1 .. 6) = "info: " then
1174 M := 7;
1176 else
1177 M := 1;
1178 end if;
1180 -- Now deal with separation between messages. Normally this is
1181 -- simply comma space, but there are some special cases.
1183 -- If continuation new line, then put actual NL character in msg
1185 if Continuation_New_Line then
1186 Newl := Newl + 1;
1187 Newm (Newl) := ASCII.LF;
1189 -- If continuation message is enclosed in parentheses, then
1190 -- special treatment (don't need a comma, and we want to combine
1191 -- successive parenthetical remarks into a single one with
1192 -- separating commas).
1194 elsif Msg_Buffer (M) = '(' and then Msg_Buffer (Msglen) = ')' then
1196 -- Case where existing message ends in right paren, remove
1197 -- and separate parenthetical remarks with a comma.
1199 if Newm (Newl) = ')' then
1200 Newm (Newl) := ',';
1201 Msg_Buffer (M) := ' ';
1203 -- Case where we are adding new parenthetical comment
1205 else
1206 Newl := Newl + 1;
1207 Newm (Newl) := ' ';
1208 end if;
1210 -- Case where continuation not in parens and no new line
1212 else
1213 Newm (Newl + 1 .. Newl + 2) := ", ";
1214 Newl := Newl + 2;
1215 end if;
1217 -- Append new message
1219 Newm (Newl + 1 .. Newl + Msglen - M + 1) :=
1220 Msg_Buffer (M .. Msglen);
1221 Newl := Newl + Msglen - M + 1;
1222 Errors.Table (Cur_Msg).Text := new String'(Newm (1 .. Newl));
1224 -- Update warning msg flag and message doc char if needed
1226 if Is_Warning_Msg then
1227 if not Errors.Table (Cur_Msg).Warn then
1228 Errors.Table (Cur_Msg).Warn := True;
1229 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1231 elsif Warning_Msg_Char /= " " then
1232 Errors.Table (Cur_Msg).Warn_Chr := Warning_Msg_Char;
1233 end if;
1234 end if;
1235 end;
1237 return;
1238 end if;
1240 -- Warning, Style and Info attributes are mutually exclusive
1242 pragma Assert (Boolean'Pos (Is_Warning_Msg) + Boolean'Pos (Is_Info_Msg) +
1243 Boolean'Pos (Is_Style_Msg) <= 1);
1245 -- Here we build a new error object
1247 Errors.Append
1248 ((Text => new String'(Msg_Buffer (1 .. Msglen)),
1249 Next => No_Error_Msg,
1250 Prev => No_Error_Msg,
1251 Sptr => Span,
1252 Optr => Opan,
1253 Insertion_Sloc => (if Has_Insertion_Line then Error_Msg_Sloc
1254 else No_Location),
1255 Sfile => Get_Source_File_Index (Sptr),
1256 Line => Get_Physical_Line_Number (Sptr),
1257 Col => Get_Column_Number (Sptr),
1258 Compile_Time_Pragma => Is_Compile_Time_Msg,
1259 Warn => Is_Warning_Msg,
1260 Info => Is_Info_Msg,
1261 Check => Is_Check_Msg,
1262 Warn_Err => False, -- reset below
1263 Warn_Chr => Warning_Msg_Char,
1264 Warn_Runtime_Raise => Is_Runtime_Raise,
1265 Style => Is_Style_Msg,
1266 Serious => Is_Serious_Error,
1267 Uncond => Is_Unconditional_Msg,
1268 Msg_Cont => Continuation,
1269 Deleted => False));
1270 Cur_Msg := Errors.Last;
1272 -- Test if warning to be treated as error
1274 Warn_Err :=
1275 (Is_Warning_Msg or Is_Style_Msg)
1276 and then (Warning_Treated_As_Error (Msg_Buffer (1 .. Msglen))
1277 or else
1278 Warning_Treated_As_Error (Get_Warning_Tag (Cur_Msg)));
1280 -- Propagate Warn_Err to this message and preceding continuations.
1281 -- Likewise, propagate Is_Warning_Msg and Is_Runtime_Raise, because the
1282 -- current continued message could have been escalated from warning to
1283 -- error.
1285 for J in reverse 1 .. Errors.Last loop
1286 Errors.Table (J).Warn_Err := Warn_Err;
1287 Errors.Table (J).Warn := Is_Warning_Msg;
1288 Errors.Table (J).Warn_Runtime_Raise := Is_Runtime_Raise;
1289 exit when not Errors.Table (J).Msg_Cont;
1290 end loop;
1292 -- If immediate errors mode set, output error message now. Also output
1293 -- now if the -d1 debug flag is set (so node number message comes out
1294 -- just before actual error message)
1296 if Debug_Flag_OO or else Debug_Flag_1 then
1297 Write_Eol;
1298 Output_Source_Line
1299 (Errors.Table (Cur_Msg).Line, Errors.Table (Cur_Msg).Sfile, True);
1300 Temp_Msg := Cur_Msg;
1301 Output_Error_Msgs (Temp_Msg);
1303 -- If not in immediate errors mode, then we insert the message in the
1304 -- error chain for later output by Finalize. The messages are sorted
1305 -- first by unit (main unit comes first), and within a unit by source
1306 -- location (earlier flag location first in the chain).
1308 else
1309 -- First a quick check, does this belong at the very end of the chain
1310 -- of error messages. This saves a lot of time in the normal case if
1311 -- there are lots of messages.
1313 if Last_Error_Msg /= No_Error_Msg
1314 and then Errors.Table (Cur_Msg).Sfile =
1315 Errors.Table (Last_Error_Msg).Sfile
1316 and then (Sptr > Errors.Table (Last_Error_Msg).Sptr.Ptr
1317 or else
1318 (Sptr = Errors.Table (Last_Error_Msg).Sptr.Ptr
1319 and then
1320 Optr > Errors.Table (Last_Error_Msg).Optr.Ptr))
1321 then
1322 Prev_Msg := Last_Error_Msg;
1323 Next_Msg := No_Error_Msg;
1325 -- Otherwise do a full sequential search for the insertion point
1327 else
1328 Prev_Msg := No_Error_Msg;
1329 Next_Msg := First_Error_Msg;
1330 while Next_Msg /= No_Error_Msg loop
1331 exit when
1332 Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
1334 if Errors.Table (Cur_Msg).Sfile = Errors.Table (Next_Msg).Sfile
1335 then
1336 exit when Sptr < Errors.Table (Next_Msg).Sptr.Ptr
1337 or else (Sptr = Errors.Table (Next_Msg).Sptr.Ptr
1338 and then
1339 Optr < Errors.Table (Next_Msg).Optr.Ptr);
1340 end if;
1342 Prev_Msg := Next_Msg;
1343 Next_Msg := Errors.Table (Next_Msg).Next;
1344 end loop;
1345 end if;
1347 -- Now we insert the new message in the error chain.
1349 -- The possible insertion point for the new message is after Prev_Msg
1350 -- and before Next_Msg. However, this is where we do a special check
1351 -- for redundant parsing messages, defined as messages posted on the
1352 -- same line. The idea here is that probably such messages are junk
1353 -- from the parser recovering. In full errors mode, we don't do this
1354 -- deletion, but otherwise such messages are discarded at this stage.
1356 if Prev_Msg /= No_Error_Msg
1357 and then Errors.Table (Prev_Msg).Line =
1358 Errors.Table (Cur_Msg).Line
1359 and then Errors.Table (Prev_Msg).Sfile =
1360 Errors.Table (Cur_Msg).Sfile
1361 and then Compiler_State = Parsing
1362 and then not All_Errors_Mode
1363 then
1364 -- Don't delete unconditional messages and at this stage, don't
1365 -- delete continuation lines; we attempted to delete those earlier
1366 -- if the parent message was deleted.
1368 if not Errors.Table (Cur_Msg).Uncond
1369 and then not Continuation
1370 then
1371 -- Don't delete if prev msg is warning and new msg is an error.
1372 -- This is because we don't want a real error masked by a
1373 -- warning. In all other cases (that is parse errors for the
1374 -- same line that are not unconditional) we do delete the
1375 -- message. This helps to avoid junk extra messages from
1376 -- cascaded parsing errors
1378 if not (Errors.Table (Prev_Msg).Warn
1379 or else
1380 Errors.Table (Prev_Msg).Style)
1381 or else
1382 (Errors.Table (Cur_Msg).Warn
1383 or else
1384 Errors.Table (Cur_Msg).Style)
1385 then
1386 -- All tests passed, delete the message by simply returning
1387 -- without any further processing.
1389 pragma Assert (not Continuation);
1391 Last_Killed := True;
1392 return;
1393 end if;
1394 end if;
1395 end if;
1397 -- Come here if message is to be inserted in the error chain
1399 if not Continuation then
1400 Last_Killed := False;
1401 end if;
1403 if Prev_Msg = No_Error_Msg then
1404 First_Error_Msg := Cur_Msg;
1405 else
1406 Errors.Table (Prev_Msg).Next := Cur_Msg;
1407 end if;
1409 Errors.Table (Cur_Msg).Next := Next_Msg;
1411 if Next_Msg = No_Error_Msg then
1412 Last_Error_Msg := Cur_Msg;
1413 end if;
1414 end if;
1416 -- Bump appropriate statistics counts
1418 if Errors.Table (Cur_Msg).Info then
1419 Info_Messages := Info_Messages + 1;
1421 elsif Errors.Table (Cur_Msg).Warn
1422 or else Errors.Table (Cur_Msg).Style
1423 then
1424 Warnings_Detected := Warnings_Detected + 1;
1426 elsif Errors.Table (Cur_Msg).Check then
1427 Check_Messages := Check_Messages + 1;
1429 else
1430 Total_Errors_Detected := Total_Errors_Detected + 1;
1432 if Errors.Table (Cur_Msg).Serious then
1433 Serious_Errors_Detected := Serious_Errors_Detected + 1;
1434 Handle_Serious_Error;
1436 -- If not serious error, set Fatal_Error to indicate ignored error
1438 else
1439 declare
1440 U : constant Unit_Number_Type := Get_Source_Unit (Sptr);
1441 begin
1442 if Fatal_Error (U) = None then
1443 Set_Fatal_Error (U, Error_Ignored);
1444 end if;
1445 end;
1446 end if;
1447 end if;
1449 -- Record warning message issued
1451 if Errors.Table (Cur_Msg).Warn
1452 and then not Errors.Table (Cur_Msg).Msg_Cont
1453 then
1454 Warning_Msg := Cur_Msg;
1455 end if;
1457 -- If too many warnings turn off warnings
1459 if Maximum_Messages /= 0 then
1460 if Warnings_Detected = Maximum_Messages then
1461 Warning_Mode := Suppress;
1462 end if;
1464 -- If too many errors abandon compilation
1466 if Total_Errors_Detected = Maximum_Messages then
1467 raise Unrecoverable_Error;
1468 end if;
1469 end if;
1471 if Has_Error_Code then
1472 declare
1473 Msg : constant String :=
1474 "\launch ""gnatprove --explain=[]"" for more information";
1475 begin
1476 Has_Double_Exclam := False;
1477 Has_Error_Code := False;
1478 Has_Insertion_Line := False;
1480 Error_Msg_Internal
1481 (Msg => Msg,
1482 Span => Span,
1483 Opan => Opan,
1484 Msg_Cont => True);
1485 end;
1486 end if;
1487 end Error_Msg_Internal;
1489 -----------------
1490 -- Error_Msg_N --
1491 -----------------
1493 procedure Error_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
1494 Fst, Lst : Node_Id;
1495 begin
1496 First_And_Last_Nodes (N, Fst, Lst);
1497 Error_Msg_NEL (Msg, N, N,
1498 To_Span (Ptr => Sloc (N),
1499 First => First_Sloc (Fst),
1500 Last => Last_Sloc (Lst)));
1501 end Error_Msg_N;
1503 ------------------
1504 -- Error_Msg_NE --
1505 ------------------
1507 procedure Error_Msg_NE
1508 (Msg : String;
1509 N : Node_Or_Entity_Id;
1510 E : Node_Or_Entity_Id)
1512 Fst, Lst : Node_Id;
1513 begin
1514 First_And_Last_Nodes (N, Fst, Lst);
1515 Error_Msg_NEL (Msg, N, E,
1516 To_Span (Ptr => Sloc (N),
1517 First => First_Sloc (Fst),
1518 Last => Last_Sloc (Lst)));
1519 end Error_Msg_NE;
1521 -------------------
1522 -- Error_Msg_NEL --
1523 -------------------
1525 procedure Error_Msg_NEL
1526 (Msg : String;
1527 N : Node_Or_Entity_Id;
1528 E : Node_Or_Entity_Id;
1529 Flag_Location : Source_Ptr)
1531 Fst, Lst : Node_Id;
1532 begin
1533 First_And_Last_Nodes (N, Fst, Lst);
1534 Error_Msg_NEL
1535 (Msg, N, E,
1536 To_Span (Ptr => Flag_Location,
1537 First => Source_Ptr'Min (Flag_Location, First_Sloc (Fst)),
1538 Last => Source_Ptr'Max (Flag_Location, Last_Sloc (Lst))));
1539 end Error_Msg_NEL;
1541 procedure Error_Msg_NEL
1542 (Msg : String;
1543 N : Node_Or_Entity_Id;
1544 E : Node_Or_Entity_Id;
1545 Flag_Span : Source_Span)
1547 begin
1548 if Special_Msg_Delete (Msg, N, E) then
1549 return;
1550 end if;
1552 Prescan_Message (Msg);
1554 -- Special handling for warning messages
1556 if Is_Warning_Msg then
1558 -- Suppress if no warnings set for either entity or node
1560 if No_Warnings (N) or else No_Warnings (E) then
1562 -- Disable any continuation messages as well
1564 Last_Killed := True;
1565 return;
1566 end if;
1567 end if;
1569 -- Test for message to be output
1571 if All_Errors_Mode
1572 or else Is_Unconditional_Msg
1573 or else Is_Warning_Msg
1574 or else OK_Node (N)
1575 or else (Msg (Msg'First) = '\' and then not Last_Killed)
1576 then
1577 Debug_Output (N);
1578 Error_Msg_Node_1 := E;
1579 Error_Msg (Msg, Flag_Span, N);
1581 else
1582 Last_Killed := True;
1583 end if;
1585 if not Get_Ignore_Errors then
1586 Set_Posted (N);
1587 end if;
1588 end Error_Msg_NEL;
1590 ------------------
1591 -- Error_Msg_NW --
1592 ------------------
1594 procedure Error_Msg_NW
1595 (Eflag : Boolean;
1596 Msg : String;
1597 N : Node_Or_Entity_Id)
1599 Fst, Lst : Node_Id;
1600 begin
1601 if Eflag
1602 and then In_Extended_Main_Source_Unit (N)
1603 and then Comes_From_Source (N)
1604 then
1605 First_And_Last_Nodes (N, Fst, Lst);
1606 Error_Msg_NEL (Msg, N, N,
1607 To_Span (Ptr => Sloc (N),
1608 First => First_Sloc (Fst),
1609 Last => Last_Sloc (Lst)));
1610 end if;
1611 end Error_Msg_NW;
1613 -----------------
1614 -- Error_Msg_S --
1615 -----------------
1617 procedure Error_Msg_S (Msg : String) is
1618 begin
1619 Error_Msg (Msg, Scan_Ptr);
1620 end Error_Msg_S;
1622 ------------------
1623 -- Error_Msg_SC --
1624 ------------------
1626 procedure Error_Msg_SC (Msg : String) is
1627 begin
1628 -- If we are at end of file, post the flag after the previous token
1630 if Token = Tok_EOF then
1631 Error_Msg_AP (Msg);
1633 -- For all other cases the message is posted at the current token
1634 -- pointer position
1636 else
1637 Error_Msg (Msg, Token_Ptr);
1638 end if;
1639 end Error_Msg_SC;
1641 ------------------
1642 -- Error_Msg_SP --
1643 ------------------
1645 procedure Error_Msg_SP (Msg : String) is
1646 begin
1647 -- Note: in the case where there is no previous token, Prev_Token_Ptr
1648 -- is set to Source_First, which is a reasonable position for the
1649 -- error flag in this situation
1651 Error_Msg (Msg, Prev_Token_Ptr);
1652 end Error_Msg_SP;
1654 --------------
1655 -- Finalize --
1656 --------------
1658 procedure Finalize (Last_Call : Boolean) is
1659 Cur : Error_Msg_Id;
1660 Nxt : Error_Msg_Id;
1661 F : Error_Msg_Id;
1663 procedure Delete_Warning (E : Error_Msg_Id);
1664 -- Delete a warning msg if not already deleted and adjust warning count
1666 --------------------
1667 -- Delete_Warning --
1668 --------------------
1670 procedure Delete_Warning (E : Error_Msg_Id) is
1671 begin
1672 if not Errors.Table (E).Deleted then
1673 Errors.Table (E).Deleted := True;
1674 Warnings_Detected := Warnings_Detected - 1;
1675 end if;
1676 end Delete_Warning;
1678 -- Start of processing for Finalize
1680 begin
1681 -- Set Prev pointers
1683 Cur := First_Error_Msg;
1684 while Cur /= No_Error_Msg loop
1685 Nxt := Errors.Table (Cur).Next;
1686 exit when Nxt = No_Error_Msg;
1687 Errors.Table (Nxt).Prev := Cur;
1688 Cur := Nxt;
1689 end loop;
1691 -- Eliminate any duplicated error messages from the list. This is
1692 -- done after the fact to avoid problems with Change_Error_Text.
1694 Cur := First_Error_Msg;
1695 while Cur /= No_Error_Msg loop
1696 Nxt := Errors.Table (Cur).Next;
1698 F := Nxt;
1699 while F /= No_Error_Msg
1700 and then Errors.Table (F).Sptr.Ptr = Errors.Table (Cur).Sptr.Ptr
1701 loop
1702 Check_Duplicate_Message (Cur, F);
1703 F := Errors.Table (F).Next;
1704 end loop;
1706 Cur := Nxt;
1707 end loop;
1709 -- Mark any messages suppressed by specific warnings as Deleted
1711 Cur := First_Error_Msg;
1712 while Cur /= No_Error_Msg loop
1713 declare
1714 CE : Error_Msg_Object renames Errors.Table (Cur);
1715 Tag : constant String := Get_Warning_Tag (Cur);
1717 begin
1718 if CE.Warn
1719 and then not CE.Deleted
1720 and then
1721 (Warning_Specifically_Suppressed (CE.Sptr.Ptr, CE.Text, Tag)
1722 /= No_String
1723 or else
1724 Warning_Specifically_Suppressed (CE.Optr.Ptr, CE.Text, Tag)
1725 /= No_String)
1726 then
1727 Delete_Warning (Cur);
1729 -- If this is a continuation, delete previous parts of message
1731 F := Cur;
1732 while Errors.Table (F).Msg_Cont loop
1733 F := Errors.Table (F).Prev;
1734 exit when F = No_Error_Msg;
1735 Delete_Warning (F);
1736 end loop;
1738 -- Delete any following continuations
1740 F := Cur;
1741 loop
1742 F := Errors.Table (F).Next;
1743 exit when F = No_Error_Msg;
1744 exit when not Errors.Table (F).Msg_Cont;
1745 Delete_Warning (F);
1746 end loop;
1747 end if;
1748 end;
1750 Cur := Errors.Table (Cur).Next;
1751 end loop;
1753 Finalize_Called := True;
1755 -- Check consistency of specific warnings (may add warnings). We only
1756 -- do this on the last call, after all possible warnings are posted.
1758 if Last_Call then
1759 Validate_Specific_Warnings;
1760 end if;
1761 end Finalize;
1763 ----------------
1764 -- First_Node --
1765 ----------------
1767 function First_Node (C : Node_Id) return Node_Id is
1768 Fst, Lst : Node_Id;
1769 begin
1770 First_And_Last_Nodes (C, Fst, Lst);
1771 return Fst;
1772 end First_Node;
1774 --------------------------
1775 -- First_And_Last_Nodes --
1776 --------------------------
1778 procedure First_And_Last_Nodes
1779 (C : Node_Id;
1780 First_Node, Last_Node : out Node_Id)
1782 Orig : constant Node_Id := Original_Node (C);
1783 Loc : constant Source_Ptr := Sloc (Orig);
1784 Sfile : constant Source_File_Index := Get_Source_File_Index (Loc);
1785 Earliest : Node_Id;
1786 Latest : Node_Id;
1787 Eloc : Source_Ptr;
1788 Lloc : Source_Ptr;
1790 function Test_First_And_Last (N : Node_Id) return Traverse_Result;
1791 -- Function applied to every node in the construct
1793 procedure Search_Tree_First_And_Last is new
1794 Traverse_Proc (Test_First_And_Last);
1795 -- Create traversal procedure
1797 -------------------------
1798 -- Test_First_And_Last --
1799 -------------------------
1801 function Test_First_And_Last (N : Node_Id) return Traverse_Result is
1802 Norig : constant Node_Id := Original_Node (N);
1803 Loc : constant Source_Ptr := Sloc (Norig);
1805 begin
1806 -- ??? For assignments that require accessiblity checks, e.g.:
1808 -- Y := Func (123);
1810 -- the function call gets an extra actual parameter association with
1811 -- Sloc of the assigned name "Y":
1813 -- Y := Func (123, A8b => 2);
1815 -- We can simply ignore those extra actual parameters when
1816 -- determining the Sloc range of the "Func (123)" expression.
1818 if Nkind (N) = N_Parameter_Association
1819 and then Is_Accessibility_Actual (N)
1820 then
1821 return Skip;
1822 end if;
1824 -- Check for earlier
1826 if Loc < Eloc
1828 -- Ignore nodes with no useful location information
1830 and then Loc /= Standard_Location
1831 and then Loc /= No_Location
1833 -- Ignore nodes from a different file. This ensures against cases
1834 -- of strange foreign code somehow being present. We don't want
1835 -- wild placement of messages if that happens.
1837 and then Get_Source_File_Index (Loc) = Sfile
1838 then
1839 Earliest := Norig;
1840 Eloc := Loc;
1841 end if;
1843 -- Check for later
1845 if Loc > Lloc
1847 -- Ignore nodes with no useful location information
1849 and then Loc /= Standard_Location
1850 and then Loc /= No_Location
1852 -- Ignore nodes from a different file. This ensures against cases
1853 -- of strange foreign code somehow being present. We don't want
1854 -- wild placement of messages if that happens.
1856 and then Get_Source_File_Index (Loc) = Sfile
1857 then
1858 Latest := Norig;
1859 Lloc := Loc;
1860 end if;
1862 return OK_Orig;
1863 end Test_First_And_Last;
1865 -- Start of processing for First_And_Last_Nodes
1867 begin
1868 if Nkind (Orig) in N_Subexpr
1869 | N_Declaration
1870 | N_Access_To_Subprogram_Definition
1871 | N_Generic_Instantiation
1872 | N_Later_Decl_Item
1873 | N_Use_Package_Clause
1874 | N_Array_Type_Definition
1875 | N_Renaming_Declaration
1876 | N_Generic_Renaming_Declaration
1877 | N_Assignment_Statement
1878 | N_Raise_Statement
1879 | N_Simple_Return_Statement
1880 | N_Exit_Statement
1881 | N_Pragma
1882 | N_Use_Type_Clause
1883 | N_With_Clause
1884 | N_Attribute_Definition_Clause
1885 | N_Subtype_Indication
1886 then
1887 Earliest := Orig;
1888 Eloc := Loc;
1889 Latest := Orig;
1890 Lloc := Loc;
1891 Search_Tree_First_And_Last (Orig);
1892 First_Node := Earliest;
1893 Last_Node := Latest;
1895 else
1896 First_Node := Orig;
1897 Last_Node := Orig;
1898 end if;
1899 end First_And_Last_Nodes;
1901 ----------------
1902 -- First_Sloc --
1903 ----------------
1905 function First_Sloc (N : Node_Id) return Source_Ptr is
1906 SI : constant Source_File_Index := Get_Source_File_Index (Sloc (N));
1907 SF : constant Source_Ptr := Source_First (SI);
1908 SL : constant Source_Ptr := Source_Last (SI);
1909 Src : constant Source_Buffer_Ptr := Source_Text (SI);
1910 F : Node_Id;
1911 S : Source_Ptr;
1913 begin
1914 F := First_Node (N);
1915 S := Sloc (F);
1917 if S not in SF .. SL then
1918 return S;
1919 end if;
1921 -- The following circuit is a bit subtle. When we have parenthesized
1922 -- expressions, then the Sloc will not record the location of the paren,
1923 -- but we would like to post the flag on the paren. So what we do is to
1924 -- crawl up the tree from the First_Node, adjusting the Sloc value for
1925 -- any parentheses we know are present. Yes, we know this circuit is not
1926 -- 100% reliable (e.g. because we don't record all possible paren level
1927 -- values), but this is only for an error message so it is good enough.
1929 Node_Loop : loop
1930 -- Include parentheses around the top node, except when they are
1931 -- required by the syntax of the parent node.
1933 exit Node_Loop when F = N
1934 and then Paren_Required (N);
1936 Paren_Loop : for J in 1 .. Paren_Count (F) loop
1938 -- We don't look more than 12 characters behind the current
1939 -- location, and in any case not past the front of the source.
1941 Search_Loop : for K in 1 .. 12 loop
1942 exit Search_Loop when S = SF;
1944 if Src (S - 1) = '(' then
1945 S := S - 1;
1946 exit Search_Loop;
1948 elsif Src (S - 1) <= ' ' then
1949 S := S - 1;
1951 else
1952 exit Search_Loop;
1953 end if;
1954 end loop Search_Loop;
1955 end loop Paren_Loop;
1957 exit Node_Loop when F = N;
1958 F := Parent (F);
1959 exit Node_Loop when Nkind (F) not in N_Subexpr;
1960 end loop Node_Loop;
1962 return S;
1963 end First_Sloc;
1965 -----------------------
1966 -- Get_Ignore_Errors --
1967 -----------------------
1969 function Get_Ignore_Errors return Boolean is
1970 begin
1971 return Errors_Must_Be_Ignored;
1972 end Get_Ignore_Errors;
1974 ----------------
1975 -- Initialize --
1976 ----------------
1978 procedure Initialize is
1979 begin
1980 Errors.Init;
1981 First_Error_Msg := No_Error_Msg;
1982 Last_Error_Msg := No_Error_Msg;
1983 Serious_Errors_Detected := 0;
1984 Total_Errors_Detected := 0;
1985 Cur_Msg := No_Error_Msg;
1986 List_Pragmas.Init;
1988 -- Reset counts for warnings
1990 Warnings_Treated_As_Errors := 0;
1991 Warnings_Detected := 0;
1992 Warnings_As_Errors_Count := 0;
1994 -- Initialize warnings tables
1996 Warnings.Init;
1997 Specific_Warnings.Init;
1998 end Initialize;
2000 -------------------------------
2001 -- Is_Size_Too_Small_Message --
2002 -------------------------------
2004 function Is_Size_Too_Small_Message (S : String) return Boolean is
2005 Size_For : constant String := "size for";
2006 pragma Assert (Size_Too_Small_Message (1 .. Size_For'Last) = Size_For);
2007 -- Assert that Size_Too_Small_Message starts with Size_For
2008 begin
2009 return S'Length >= Size_For'Length
2010 and then S (S'First .. S'First + Size_For'Length - 1) = Size_For;
2011 -- True if S starts with Size_For
2012 end Is_Size_Too_Small_Message;
2014 --------------------------------
2015 -- Validate_Specific_Warnings --
2016 --------------------------------
2018 procedure Validate_Specific_Warnings is
2019 begin
2020 if not Warnsw.Warn_On_Warnings_Off then
2021 return;
2022 end if;
2024 for J in Specific_Warnings.First .. Specific_Warnings.Last loop
2025 declare
2026 SWE : Specific_Warning_Entry renames Specific_Warnings.Table (J);
2028 begin
2029 if not SWE.Config then
2031 -- Warn for unmatched Warnings (Off, ...)
2033 if SWE.Open then
2034 Error_Msg
2035 ("?.w?pragma Warnings Off with no matching Warnings On",
2036 SWE.Start);
2038 -- Warn for ineffective Warnings (Off, ..)
2040 elsif not SWE.Used
2042 -- Do not issue this warning for -Wxxx messages since the
2043 -- back-end doesn't report the information. Note that there
2044 -- is always an asterisk at the start of every message.
2046 and then not
2047 (SWE.Msg'Length > 3 and then SWE.Msg (2 .. 3) = "-W")
2048 then
2049 Error_Msg
2050 ("?.w?no warning suppressed by this pragma",
2051 SWE.Start);
2052 end if;
2053 end if;
2054 end;
2055 end loop;
2056 end Validate_Specific_Warnings;
2058 ---------------
2059 -- Last_Node --
2060 ---------------
2062 function Last_Node (C : Node_Id) return Node_Id is
2063 Fst, Lst : Node_Id;
2064 begin
2065 First_And_Last_Nodes (C, Fst, Lst);
2066 return Lst;
2067 end Last_Node;
2069 ---------------
2070 -- Last_Sloc --
2071 ---------------
2073 function Last_Sloc (N : Node_Id) return Source_Ptr is
2074 procedure Skip_Char (S : in out Source_Ptr);
2075 -- Skip one character of the source buffer at location S
2077 ---------------
2078 -- Skip_Char --
2079 ---------------
2081 procedure Skip_Char (S : in out Source_Ptr) is
2082 begin
2083 S := S + 1;
2084 end Skip_Char;
2086 -- Local variables
2088 SI : constant Source_File_Index := Get_Source_File_Index (Sloc (N));
2089 SF : constant Source_Ptr := Source_First (SI);
2090 SL : constant Source_Ptr := Source_Last (SI);
2091 Src : constant Source_Buffer_Ptr := Source_Text (SI);
2092 F : Node_Id;
2093 S : Source_Ptr;
2095 -- Start of processing for Last_Sloc
2097 begin
2098 F := Last_Node (N);
2099 S := Sloc (F);
2101 if S not in SF .. SL then
2102 return S;
2103 end if;
2105 -- For string and character literals simply forward the sloc by their
2106 -- length including the closing quotes. Perhaps we should do something
2107 -- special for multibyte characters, but this code is only used to emit
2108 -- error messages, so it is not worth the effort.
2110 case Nkind (F) is
2111 when N_String_Literal =>
2112 return S + Source_Ptr (String_Length (Strval (F))) + 1;
2114 when N_Character_Literal =>
2115 return S + 2;
2117 -- Skip past integer literals, both decimal and based, integer and
2118 -- real. We can't greedily accept all allowed character, because
2119 -- we would consme too many of them in expressions like "123+ABC"
2120 -- or "123..456", so we follow quite precisely the Ada grammar and
2121 -- consume different characters depending on the context.
2123 when N_Integer_Literal =>
2125 -- Skip past the initial numeral, which either leads the decimal
2126 -- literal or is the base of a based literal.
2128 while S < SL
2129 and then Src (S + 1) in '0' .. '9' | '_'
2130 loop
2131 Skip_Char (S);
2132 end loop;
2134 -- Skip past #based_numeral#, if present
2136 if S < SL
2137 and then Src (S + 1) = '#'
2138 then
2139 Skip_Char (S);
2141 while S < SL
2142 and then
2143 Src (S + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'
2144 loop
2145 Skip_Char (S);
2146 end loop;
2148 if S < SL
2149 and then Src (S + 1) = '#'
2150 then
2151 Skip_Char (S);
2152 end if;
2153 end if;
2155 -- Skip past exponent, if present
2157 if S < SL
2158 and then Src (S + 1) in 'e' | 'E'
2159 then
2160 Skip_Char (S);
2162 -- For positive exponents the plus sign is optional, but we
2163 -- can simply skip past both plus and minus.
2165 if S < SL
2166 and then Src (S + 1) in '+' | '-'
2167 then
2168 Skip_Char (S);
2169 end if;
2171 -- Skip past the numeral part
2173 while S < SL
2174 and then Src (S + 1) in '0' .. '9' | '_'
2175 loop
2176 Skip_Char (S);
2177 end loop;
2178 end if;
2180 when N_Real_Literal =>
2181 -- Skip past the initial numeral, which either leads the decimal
2182 -- literal or is the base of a based literal.
2184 while S < SL
2185 and then Src (S + 1) in '0' .. '9' | '_'
2186 loop
2187 Skip_Char (S);
2188 end loop;
2190 if S < SL then
2192 -- Skip the dot and continue with a decimal literal
2194 if Src (S + 1) = '.' then
2195 Skip_Char (S);
2197 while S < SL
2198 and then Src (S + 1) in '0' .. '9' | '_'
2199 loop
2200 Skip_Char (S);
2201 end loop;
2203 -- Skip the hash and continue with a based literal
2205 elsif Src (S + 1) = '#' then
2206 Skip_Char (S);
2208 while S < SL
2209 and then
2210 Src (S + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'
2211 loop
2212 Skip_Char (S);
2213 end loop;
2215 if S < SL
2216 and then Src (S + 1) = '.'
2217 then
2218 Skip_Char (S);
2219 end if;
2221 while S < SL
2222 and then
2223 Src (S + 1) in '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' | '_'
2224 loop
2225 Skip_Char (S);
2226 end loop;
2228 if S < SL
2229 and then Src (S + 1) = '#'
2230 then
2231 Skip_Char (S);
2232 end if;
2233 end if;
2234 end if;
2236 -- Skip past exponent, if present
2238 if S < SL
2239 and then Src (S + 1) in 'e' | 'E'
2240 then
2241 Skip_Char (S);
2242 -- For positive exponents the plus sign is optional, but we
2243 -- can simply skip past both plus and minus.
2245 if Src (S + 1) in '+' | '-' then
2246 Skip_Char (S);
2247 end if;
2249 -- Skip past the numeral part
2251 while S < SL
2252 and then Src (S + 1) in '0' .. '9' | '_'
2253 loop
2254 Skip_Char (S);
2255 end loop;
2256 end if;
2258 -- For other nodes simply skip past a keyword/identifier
2260 when others =>
2261 while S in SF .. SL - 1
2262 and then Src (S + 1)
2264 '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' | '_'
2265 loop
2266 Skip_Char (S);
2267 end loop;
2268 end case;
2270 -- The following circuit attempts at crawling up the tree from the
2271 -- Last_Node, adjusting the Sloc value for any parentheses we know
2272 -- are present, similarly to what is done in First_Sloc.
2274 Node_Loop : loop
2275 -- Include parentheses around the top node, except when they are
2276 -- required by the syntax of the parent node.
2278 exit Node_Loop when F = N
2279 and then Paren_Required (N);
2281 Paren_Loop : for J in 1 .. Paren_Count (F) loop
2283 -- We don't look more than 12 characters after the current
2284 -- location
2286 Search_Loop : for K in 1 .. 12 loop
2287 exit Node_Loop when S = SL;
2289 if Src (S + 1) = ')' then
2290 S := S + 1;
2291 exit Search_Loop;
2293 elsif Src (S + 1) <= ' ' then
2294 S := S + 1;
2296 else
2297 exit Search_Loop;
2298 end if;
2299 end loop Search_Loop;
2300 end loop Paren_Loop;
2302 exit Node_Loop when F = N;
2303 F := Parent (F);
2304 exit Node_Loop when Nkind (F) not in N_Subexpr;
2305 end loop Node_Loop;
2307 -- Remove any trailing space
2309 while S in SF + 1 .. SL
2310 and then Src (S) = ' '
2311 loop
2312 S := S - 1;
2313 end loop;
2315 return S;
2316 end Last_Sloc;
2318 -----------------
2319 -- No_Warnings --
2320 -----------------
2322 function No_Warnings (N : Node_Or_Entity_Id) return Boolean is
2323 begin
2324 if Error_Posted (N) then
2325 return True;
2327 elsif Nkind (N) in N_Entity and then Has_Warnings_Off (N) then
2328 return True;
2330 elsif Is_Entity_Name (N)
2331 and then Present (Entity (N))
2332 and then Has_Warnings_Off (Entity (N))
2333 then
2334 return True;
2336 else
2337 return False;
2338 end if;
2339 end No_Warnings;
2341 -------------
2342 -- OK_Node --
2343 -------------
2345 function OK_Node (N : Node_Id) return Boolean is
2346 K : constant Node_Kind := Nkind (N);
2348 begin
2349 if Error_Posted (N) then
2350 return False;
2352 elsif K in N_Has_Etype
2353 and then Present (Etype (N))
2354 and then Error_Posted (Etype (N))
2355 then
2356 return False;
2358 elsif (K in N_Op
2359 or else K = N_Attribute_Reference
2360 or else K = N_Character_Literal
2361 or else K = N_Expanded_Name
2362 or else K = N_Identifier
2363 or else K = N_Operator_Symbol)
2364 and then Present (Entity (N))
2365 and then Error_Posted (Entity (N))
2366 then
2367 return False;
2368 else
2369 return True;
2370 end if;
2371 end OK_Node;
2373 -------------------------
2374 -- Output_JSON_Message --
2375 -------------------------
2377 procedure Output_JSON_Message (Error_Id : Error_Msg_Id) is
2379 function Is_Continuation (E : Error_Msg_Id) return Boolean;
2380 -- Return True if E is a continuation message.
2382 procedure Write_JSON_Escaped_String (Str : String_Ptr);
2383 procedure Write_JSON_Escaped_String (Str : String);
2384 -- Write each character of Str, taking care of preceding each quote and
2385 -- backslash with a backslash. Note that this escaping differs from what
2386 -- GCC does.
2388 -- Indeed, the JSON specification mandates encoding wide characters
2389 -- either as their direct UTF-8 representation or as their escaped
2390 -- UTF-16 surrogate pairs representation. GCC seems to prefer escaping -
2391 -- we choose to use the UTF-8 representation instead.
2393 procedure Write_JSON_Location (Sptr : Source_Ptr);
2394 -- Write Sptr as a JSON location, an object containing a file attribute,
2395 -- a line number and a column number.
2397 procedure Write_JSON_Span (Error : Error_Msg_Object);
2398 -- Write Error as a JSON span, an object containing a "caret" attribute
2399 -- whose value is the JSON location of Error.Sptr.Ptr. If Sptr.First and
2400 -- Sptr.Last are different from Sptr.Ptr, they will be printed as JSON
2401 -- locations under the names "start" and "finish".
2403 -----------------------
2404 -- Is_Continuation --
2405 -----------------------
2407 function Is_Continuation (E : Error_Msg_Id) return Boolean is
2408 begin
2409 return E <= Last_Error_Msg and then Errors.Table (E).Msg_Cont;
2410 end Is_Continuation;
2412 -------------------------------
2413 -- Write_JSON_Escaped_String --
2414 -------------------------------
2416 procedure Write_JSON_Escaped_String (Str : String) is
2417 begin
2418 for C of Str loop
2419 if C = '"' or else C = '\' then
2420 Write_Char ('\');
2421 end if;
2423 Write_Char (C);
2424 end loop;
2425 end Write_JSON_Escaped_String;
2427 -------------------------------
2428 -- Write_JSON_Escaped_String --
2429 -------------------------------
2431 procedure Write_JSON_Escaped_String (Str : String_Ptr) is
2432 begin
2433 Write_JSON_Escaped_String (Str.all);
2434 end Write_JSON_Escaped_String;
2436 -------------------------
2437 -- Write_JSON_Location --
2438 -------------------------
2440 procedure Write_JSON_Location (Sptr : Source_Ptr) is
2441 Name : constant File_Name_Type :=
2442 Full_Ref_Name (Get_Source_File_Index (Sptr));
2443 begin
2444 Write_Str ("{""file"":""");
2445 if Full_Path_Name_For_Brief_Errors then
2446 Write_JSON_Escaped_String
2447 (System.OS_Lib.Normalize_Pathname (Get_Name_String (Name)));
2448 else
2449 Write_Name (Name);
2450 end if;
2451 Write_Str (""",""line"":");
2452 Write_Int (Pos (Get_Physical_Line_Number (Sptr)));
2453 Write_Str (", ""column"":");
2454 Write_Int (Nat (Get_Column_Number (Sptr)));
2455 Write_Str ("}");
2456 end Write_JSON_Location;
2458 ---------------------
2459 -- Write_JSON_Span --
2460 ---------------------
2462 procedure Write_JSON_Span (Error : Error_Msg_Object) is
2463 Span : constant Source_Span := Error.Sptr;
2464 begin
2465 Write_Str ("{""caret"":");
2466 Write_JSON_Location (Span.Ptr);
2468 if Span.Ptr /= Span.First then
2469 Write_Str (",""start"":");
2470 Write_JSON_Location (Span.First);
2471 end if;
2473 if Span.Ptr /= Span.Last then
2474 Write_Str (",""finish"":");
2475 Write_JSON_Location (Span.Last);
2476 end if;
2478 Write_Str ("}");
2479 end Write_JSON_Span;
2481 -- Local Variables
2483 E : Error_Msg_Id := Error_Id;
2485 Print_Continuations : constant Boolean := not Is_Continuation (E);
2486 -- Do not print continuations messages as children of the current
2487 -- message if the current message is a continuation message.
2489 Option : constant String := Get_Warning_Option (E);
2490 -- The option that triggered this message.
2492 -- Start of processing for Output_JSON_Message
2494 begin
2495 -- Print message kind
2497 Write_Str ("{""kind"":");
2499 if Errors.Table (E).Warn and then not Errors.Table (E).Warn_Err then
2500 Write_Str ("""warning""");
2501 elsif Errors.Table (E).Info or else Errors.Table (E).Check then
2502 Write_Str ("""note""");
2503 else
2504 Write_Str ("""error""");
2505 end if;
2507 -- Print message location
2509 Write_Str (",""locations"":[");
2510 Write_JSON_Span (Errors.Table (E));
2512 if Errors.Table (E).Optr.Ptr /= Errors.Table (E).Sptr.Ptr then
2513 Write_Str (",{""caret"":");
2514 Write_JSON_Location (Errors.Table (E).Optr.Ptr);
2515 Write_Str ("}");
2516 end if;
2518 Write_Str ("]");
2520 -- Print message option, if there is one
2521 if Option /= "" then
2522 Write_Str (",""option"":""" & Option & """");
2523 end if;
2525 -- Print message content
2527 Write_Str (",""message"":""");
2528 Write_JSON_Escaped_String (Errors.Table (E).Text);
2529 Write_Str ("""");
2531 E := E + 1;
2533 if Print_Continuations and then Is_Continuation (E) then
2535 Write_Str (",""children"": [");
2536 Output_JSON_Message (E);
2537 E := E + 1;
2539 while Is_Continuation (E) loop
2540 Write_Str (", ");
2541 Output_JSON_Message (E);
2542 E := E + 1;
2543 end loop;
2545 Write_Str ("]");
2547 end if;
2549 Write_Str ("}");
2550 end Output_JSON_Message;
2552 ---------------------
2553 -- Output_Messages --
2554 ---------------------
2556 procedure Output_Messages is
2558 -- Local subprograms
2560 procedure Emit_Error_Msgs;
2561 -- Emit all error messages in the table use the pretty printed format if
2562 -- -gnatdF is used otherwise use the brief format.
2564 procedure Write_Error_Summary;
2565 -- Write error summary
2567 procedure Write_Header (Sfile : Source_File_Index);
2568 -- Write header line (compiling or checking given file)
2570 procedure Write_Max_Errors;
2571 -- Write message if max errors reached
2573 procedure Write_Source_Code_Lines
2574 (Span : Source_Span;
2575 SGR_Span : String);
2576 -- Write the source code line corresponding to Span, as follows when
2577 -- Span in on one line:
2579 -- line | actual code line here with Span somewhere
2580 -- | ~~~~~^~~~
2582 -- where the caret on the line points to location Span.Ptr, and the
2583 -- range Span.First..Span.Last is underlined.
2585 -- or when the span is over multiple lines:
2587 -- line | beginning of the Span on this line
2588 -- ... | ...
2589 -- line>| actual code line here with Span.Ptr somewhere
2590 -- ... | ...
2591 -- line | end of the Span on this line
2593 -- or when the span is a simple location, as follows:
2595 -- line | actual code line here with Span somewhere
2596 -- | ^ here
2598 -- where the caret on the line points to location Span.Ptr
2600 -- SGR_Span is the SGR string to start the section of code in the span,
2601 -- that should be closed with SGR_Reset.
2603 --------------------
2604 -- Emit_Error_Msgs --
2605 ---------------------
2607 procedure Emit_Error_Msgs is
2608 Use_Prefix : Boolean;
2609 E : Error_Msg_Id;
2610 begin
2611 Set_Standard_Error;
2613 E := First_Error_Msg;
2614 while E /= No_Error_Msg loop
2616 -- If -gnatdF is used, separate main messages from previous
2617 -- messages with a newline (unless it is an info message) and
2618 -- make continuation messages follow the main message with only
2619 -- an indentation of two space characters, without repeating
2620 -- file:line:col: prefix.
2622 Use_Prefix :=
2623 not (Debug_Flag_FF and then Errors.Table (E).Msg_Cont);
2625 if not Errors.Table (E).Deleted then
2627 if Debug_Flag_FF then
2628 if Errors.Table (E).Msg_Cont then
2629 Write_Str (" ");
2630 elsif not Errors.Table (E).Info then
2631 Write_Eol;
2632 end if;
2633 end if;
2635 if Use_Prefix then
2636 Write_Str (SGR_Locus);
2638 if Full_Path_Name_For_Brief_Errors then
2639 Write_Name (Full_Ref_Name (Errors.Table (E).Sfile));
2640 else
2641 Write_Name (Reference_Name (Errors.Table (E).Sfile));
2642 end if;
2644 Write_Char (':');
2645 Write_Int (Int (Physical_To_Logical
2646 (Errors.Table (E).Line,
2647 Errors.Table (E).Sfile)));
2648 Write_Char (':');
2650 if Errors.Table (E).Col < 10 then
2651 Write_Char ('0');
2652 end if;
2654 Write_Int (Int (Errors.Table (E).Col));
2655 Write_Str (": ");
2657 Write_Str (SGR_Reset);
2658 end if;
2660 Output_Msg_Text (E);
2661 Write_Eol;
2663 -- If -gnatdF is used, write the source code line
2664 -- corresponding to the location of the main message (unless
2665 -- it is an info message). Also write the source code line
2666 -- corresponding to an insertion location inside
2667 -- continuation messages.
2669 if Debug_Flag_FF
2670 and then not Errors.Table (E).Info
2671 then
2672 if Errors.Table (E).Msg_Cont then
2673 declare
2674 Loc : constant Source_Ptr :=
2675 Errors.Table (E).Insertion_Sloc;
2676 begin
2677 if Loc /= No_Location then
2678 Write_Source_Code_Lines
2679 (To_Span (Loc), SGR_Span => SGR_Note);
2680 end if;
2681 end;
2683 else
2684 declare
2685 SGR_Span : constant String :=
2686 (if Errors.Table (E).Info then SGR_Note
2687 elsif Errors.Table (E).Warn
2688 and then not Errors.Table (E).Warn_Err
2689 then SGR_Warning
2690 else SGR_Error);
2691 begin
2692 Write_Source_Code_Lines
2693 (Errors.Table (E).Optr, SGR_Span);
2694 end;
2695 end if;
2696 end if;
2697 end if;
2699 E := Errors.Table (E).Next;
2700 end loop;
2702 Set_Standard_Output;
2703 end Emit_Error_Msgs;
2705 -------------------------
2706 -- Write_Error_Summary --
2707 -------------------------
2709 procedure Write_Error_Summary is
2710 begin
2711 -- Extra blank line if error messages or source listing were output
2713 if Total_Errors_Detected + Warnings_Detected > 0 or else Full_List
2714 then
2715 Write_Eol;
2716 end if;
2718 -- Message giving number of lines read and number of errors detected.
2719 -- This normally goes to Standard_Output. The exception is when brief
2720 -- mode is not set, verbose mode (or full list mode) is set, and
2721 -- there are errors. In this case we send the message to standard
2722 -- error to make sure that *something* appears on standard error
2723 -- in an error situation.
2725 if Total_Errors_Detected + Warnings_Detected /= 0
2726 and then not Brief_Output
2727 and then (Verbose_Mode or Full_List)
2728 then
2729 Set_Standard_Error;
2730 end if;
2732 -- Message giving total number of lines. Don't give this message if
2733 -- the Main_Source line is unknown (this happens in error situations,
2734 -- e.g. when integrated preprocessing fails).
2736 if Main_Source_File > No_Source_File then
2737 Write_Str (" ");
2738 Write_Int (Num_Source_Lines (Main_Source_File));
2740 if Num_Source_Lines (Main_Source_File) = 1 then
2741 Write_Str (" line: ");
2742 else
2743 Write_Str (" lines: ");
2744 end if;
2745 end if;
2747 if Total_Errors_Detected = 0 then
2748 Write_Str ("No errors");
2750 elsif Total_Errors_Detected = 1 then
2751 Write_Str ("1 error");
2753 else
2754 Write_Int (Total_Errors_Detected);
2755 Write_Str (" errors");
2756 end if;
2758 -- We now need to output warnings. When using -gnatwe, all warnings
2759 -- should be treated as errors, except for warnings originating from
2760 -- the use of the Compile_Time_Warning pragma. Another situation
2761 -- where a warning might be treated as an error is when the source
2762 -- code contains a Warning_As_Error pragma.
2763 -- When warnings are treated as errors, we still log them as
2764 -- warnings, but we add a message denoting how many of these warnings
2765 -- are also errors.
2767 declare
2768 Warnings_Count : constant Int := Warnings_Detected;
2770 Compile_Time_Warnings : Int;
2771 -- Number of warnings that come from a Compile_Time_Warning
2772 -- pragma.
2774 Non_Compile_Time_Warnings : Int;
2775 -- Number of warnings that do not come from a Compile_Time_Warning
2776 -- pragmas.
2778 begin
2779 if Warnings_Count > 0 then
2780 Write_Str (", ");
2781 Write_Int (Warnings_Count);
2782 Write_Str (" warning");
2784 if Warnings_Count > 1 then
2785 Write_Char ('s');
2786 end if;
2788 Compile_Time_Warnings := Count_Compile_Time_Pragma_Warnings;
2789 Non_Compile_Time_Warnings :=
2790 Warnings_Count - Compile_Time_Warnings;
2792 if Warning_Mode = Treat_As_Error
2793 and then Non_Compile_Time_Warnings > 0
2794 then
2795 Write_Str (" (");
2797 if Compile_Time_Warnings > 0 then
2798 Write_Int (Non_Compile_Time_Warnings);
2799 Write_Str (" ");
2800 end if;
2802 Write_Str ("treated as error");
2804 if Non_Compile_Time_Warnings > 1 then
2805 Write_Char ('s');
2806 end if;
2808 Write_Char (')');
2810 elsif Warnings_Treated_As_Errors > 0 then
2811 Write_Str (" (");
2813 if Warnings_Treated_As_Errors /= Warnings_Count then
2814 Write_Int (Warnings_Treated_As_Errors);
2815 Write_Str (" ");
2816 end if;
2818 Write_Str ("treated as error");
2820 if Warnings_Treated_As_Errors > 1 then
2821 Write_Str ("s");
2822 end if;
2824 Write_Str (")");
2825 end if;
2826 end if;
2827 end;
2829 if Info_Messages /= 0 then
2830 Write_Str (", ");
2831 Write_Int (Info_Messages);
2832 Write_Str (" info message");
2834 if Info_Messages > 1 then
2835 Write_Char ('s');
2836 end if;
2837 end if;
2839 Write_Eol;
2840 Set_Standard_Output;
2841 end Write_Error_Summary;
2843 ------------------
2844 -- Write_Header --
2845 ------------------
2847 procedure Write_Header (Sfile : Source_File_Index) is
2848 begin
2849 if Verbose_Mode or Full_List then
2850 if Original_Operating_Mode = Generate_Code then
2851 Write_Str ("Compiling: ");
2852 else
2853 Write_Str ("Checking: ");
2854 end if;
2856 Write_Name (Full_File_Name (Sfile));
2858 if not Debug_Flag_7 then
2859 Write_Eol;
2860 Write_Str ("Source file time stamp: ");
2861 Write_Time_Stamp (Sfile);
2862 Write_Eol;
2863 Write_Str ("Compiled at: " & Compilation_Time);
2864 end if;
2866 Write_Eol;
2867 end if;
2868 end Write_Header;
2870 ----------------------
2871 -- Write_Max_Errors --
2872 ----------------------
2874 procedure Write_Max_Errors is
2875 begin
2876 if Maximum_Messages /= 0 then
2877 if Warnings_Detected >= Maximum_Messages then
2878 Set_Standard_Error;
2879 Write_Line ("maximum number of warnings output");
2880 Write_Line ("any further warnings suppressed");
2881 Set_Standard_Output;
2882 end if;
2884 -- If too many errors print message
2886 if Total_Errors_Detected >= Maximum_Messages then
2887 Set_Standard_Error;
2888 Write_Line ("fatal error: maximum number of errors detected");
2889 Set_Standard_Output;
2890 end if;
2891 end if;
2892 end Write_Max_Errors;
2894 -----------------------------
2895 -- Write_Source_Code_Lines --
2896 -----------------------------
2898 procedure Write_Source_Code_Lines
2899 (Span : Source_Span;
2900 SGR_Span : String)
2902 function Get_Line_End
2903 (Buf : Source_Buffer_Ptr;
2904 Loc : Source_Ptr) return Source_Ptr;
2905 -- Get the source location for the end of the line in Buf for Loc. If
2906 -- Loc is past the end of Buf already, return Buf'Last.
2908 function Get_Line_Start
2909 (Buf : Source_Buffer_Ptr;
2910 Loc : Source_Ptr) return Source_Ptr;
2911 -- Get the source location for the start of the line in Buf for Loc
2913 function Image (X : Positive; Width : Positive) return String;
2914 -- Output number X over Width characters, with whitespace padding.
2915 -- Only output the low-order Width digits of X, if X is larger than
2916 -- Width digits.
2918 procedure Write_Buffer
2919 (Buf : Source_Buffer_Ptr;
2920 First : Source_Ptr;
2921 Last : Source_Ptr);
2922 -- Output the characters from First to Last position in Buf, using
2923 -- Write_Buffer_Char.
2925 procedure Write_Buffer_Char
2926 (Buf : Source_Buffer_Ptr;
2927 Loc : Source_Ptr);
2928 -- Output the characters at position Loc in Buf, translating ASCII.HT
2929 -- in a suitable number of spaces so that the output is not modified
2930 -- by starting in a different column that 1.
2932 procedure Write_Line_Marker
2933 (Num : Pos;
2934 Mark : Boolean;
2935 Width : Positive);
2936 -- Output the line number Num over Width characters, with possibly
2937 -- a Mark to denote the line with the main location when reporting
2938 -- a span over multiple lines.
2940 ------------------
2941 -- Get_Line_End --
2942 ------------------
2944 function Get_Line_End
2945 (Buf : Source_Buffer_Ptr;
2946 Loc : Source_Ptr) return Source_Ptr
2948 Cur_Loc : Source_Ptr := Source_Ptr'Min (Loc, Buf'Last);
2949 begin
2950 while Cur_Loc < Buf'Last
2951 and then Buf (Cur_Loc) /= ASCII.LF
2952 loop
2953 Cur_Loc := Cur_Loc + 1;
2954 end loop;
2956 return Cur_Loc;
2957 end Get_Line_End;
2959 --------------------
2960 -- Get_Line_Start --
2961 --------------------
2963 function Get_Line_Start
2964 (Buf : Source_Buffer_Ptr;
2965 Loc : Source_Ptr) return Source_Ptr
2967 Cur_Loc : Source_Ptr := Loc;
2968 begin
2969 while Cur_Loc > Buf'First
2970 and then Buf (Cur_Loc - 1) /= ASCII.LF
2971 loop
2972 Cur_Loc := Cur_Loc - 1;
2973 end loop;
2975 return Cur_Loc;
2976 end Get_Line_Start;
2978 -----------
2979 -- Image --
2980 -----------
2982 function Image (X : Positive; Width : Positive) return String is
2983 Str : String (1 .. Width);
2984 Curr : Natural := X;
2985 begin
2986 for J in reverse 1 .. Width loop
2987 if Curr > 0 then
2988 Str (J) := Character'Val (Character'Pos ('0') + Curr mod 10);
2989 Curr := Curr / 10;
2990 else
2991 Str (J) := ' ';
2992 end if;
2993 end loop;
2995 return Str;
2996 end Image;
2998 ------------------
2999 -- Write_Buffer --
3000 ------------------
3002 procedure Write_Buffer
3003 (Buf : Source_Buffer_Ptr;
3004 First : Source_Ptr;
3005 Last : Source_Ptr)
3007 begin
3008 for Loc in First .. Last loop
3009 Write_Buffer_Char (Buf, Loc);
3010 end loop;
3011 end Write_Buffer;
3013 -----------------------
3014 -- Write_Buffer_Char --
3015 -----------------------
3017 procedure Write_Buffer_Char
3018 (Buf : Source_Buffer_Ptr;
3019 Loc : Source_Ptr)
3021 begin
3022 -- If the character ASCII.HT is not the last one in the file,
3023 -- output as many spaces as the character represents in the
3024 -- original source file.
3026 if Buf (Loc) = ASCII.HT
3027 and then Loc < Buf'Last
3028 then
3029 for X in Get_Column_Number (Loc) ..
3030 Get_Column_Number (Loc + 1) - 1
3031 loop
3032 Write_Char (' ');
3033 end loop;
3035 -- Otherwise output the character itself
3037 else
3038 Write_Char (Buf (Loc));
3039 end if;
3040 end Write_Buffer_Char;
3042 -----------------------
3043 -- Write_Line_Marker --
3044 -----------------------
3046 procedure Write_Line_Marker
3047 (Num : Pos;
3048 Mark : Boolean;
3049 Width : Positive)
3051 begin
3052 Write_Str (Image (Positive (Num), Width => Width));
3053 Write_Str ((if Mark then ">" else " ") & "|");
3054 end Write_Line_Marker;
3056 -- Local variables
3058 Loc : constant Source_Ptr := Span.Ptr;
3059 Line : constant Pos := Pos (Get_Physical_Line_Number (Loc));
3061 Col : constant Natural := Natural (Get_Column_Number (Loc));
3063 Fst : constant Source_Ptr := Span.First;
3064 Line_Fst : constant Pos :=
3065 Pos (Get_Physical_Line_Number (Fst));
3066 Col_Fst : constant Natural :=
3067 Natural (Get_Column_Number (Fst));
3068 Lst : constant Source_Ptr := Span.Last;
3069 Line_Lst : constant Pos :=
3070 Pos (Get_Physical_Line_Number (Lst));
3071 Col_Lst : constant Natural :=
3072 Natural (Get_Column_Number (Lst));
3074 Width : constant := 5;
3075 Buf : Source_Buffer_Ptr;
3076 Cur_Loc : Source_Ptr := Fst;
3077 Cur_Line : Pos := Line_Fst;
3079 -- Start of processing for Write_Source_Code_Lines
3081 begin
3082 if Loc >= First_Source_Ptr then
3083 Buf := Source_Text (Get_Source_File_Index (Loc));
3085 -- First line of the span with actual source code. We retrieve
3086 -- the beginning of the line instead of relying on Col_Fst, as
3087 -- ASCII.HT characters change column numbers by possibly more
3088 -- than one.
3090 Write_Line_Marker
3091 (Cur_Line,
3092 Line_Fst /= Line_Lst and then Cur_Line = Line,
3093 Width);
3094 Write_Buffer (Buf, Get_Line_Start (Buf, Cur_Loc), Cur_Loc - 1);
3096 -- Output the first/caret/last lines of the span, as well as
3097 -- lines that are directly above/below the caret if they complete
3098 -- the gap with first/last lines, otherwise use ... to denote
3099 -- intermediate lines.
3101 -- If the span is on one line and not a simple source location,
3102 -- color it appropriately.
3104 if Line_Fst = Line_Lst
3105 and then Col_Fst /= Col_Lst
3106 then
3107 Write_Str (SGR_Span);
3108 end if;
3110 declare
3111 function Do_Write_Line (Cur_Line : Pos) return Boolean is
3112 (Cur_Line in Line_Fst | Line | Line_Lst
3113 or else
3114 (Cur_Line = Line_Fst + 1 and then Cur_Line = Line - 1)
3115 or else
3116 (Cur_Line = Line + 1 and then Cur_Line = Line_Lst - 1));
3117 begin
3118 while Cur_Loc <= Buf'Last
3119 and then Cur_Loc <= Lst
3120 loop
3121 if Do_Write_Line (Cur_Line) then
3122 Write_Buffer_Char (Buf, Cur_Loc);
3123 end if;
3125 if Buf (Cur_Loc) = ASCII.LF then
3126 Cur_Line := Cur_Line + 1;
3128 -- Output ... for skipped lines
3130 if (Cur_Line = Line
3131 and then not Do_Write_Line (Cur_Line - 1))
3132 or else
3133 (Cur_Line = Line + 1
3134 and then not Do_Write_Line (Cur_Line))
3135 then
3136 Write_Str ((1 .. Width - 3 => ' ') & "... | ...");
3137 Write_Eol;
3138 end if;
3140 -- Display the line marker if the line should be
3141 -- displayed.
3143 if Do_Write_Line (Cur_Line) then
3144 Write_Line_Marker
3145 (Cur_Line,
3146 Line_Fst /= Line_Lst and then Cur_Line = Line,
3147 Width);
3148 end if;
3149 end if;
3151 Cur_Loc := Cur_Loc + 1;
3152 end loop;
3153 end;
3155 if Line_Fst = Line_Lst
3156 and then Col_Fst /= Col_Lst
3157 then
3158 Write_Str (SGR_Reset);
3159 end if;
3161 -- Output the rest of the last line of the span
3163 Write_Buffer (Buf, Cur_Loc, Get_Line_End (Buf, Cur_Loc));
3165 -- If the span is on one line, output a second line with caret
3166 -- sign pointing to location Loc
3168 if Line_Fst = Line_Lst then
3169 Write_Str (String'(1 .. Width => ' '));
3170 Write_Str (" |");
3171 Write_Str (String'(1 .. Col_Fst - 1 => ' '));
3173 Write_Str (SGR_Span);
3175 Write_Str (String'(Col_Fst .. Col - 1 => '~'));
3176 Write_Str ("^");
3177 Write_Str (String'(Col + 1 .. Col_Lst => '~'));
3179 -- If the span is really just a location, add the word "here"
3180 -- to clarify this is the location for the message.
3182 if Col_Fst = Col_Lst then
3183 Write_Str (" here");
3184 end if;
3186 Write_Str (SGR_Reset);
3188 Write_Eol;
3189 end if;
3190 end if;
3191 end Write_Source_Code_Lines;
3193 -- Local variables
3195 E : Error_Msg_Id;
3196 Err_Flag : Boolean;
3198 -- Start of processing for Output_Messages
3200 begin
3201 -- Error if Finalize has not been called
3203 if not Finalize_Called then
3204 raise Program_Error;
3205 end if;
3207 -- Reset current error source file if the main unit has a pragma
3208 -- Source_Reference. This ensures outputting the proper name of
3209 -- the source file in this situation.
3211 if Main_Source_File <= No_Source_File
3212 or else Num_SRef_Pragmas (Main_Source_File) /= 0
3213 then
3214 Current_Error_Source_File := No_Source_File;
3215 end if;
3217 if Opt.JSON_Output then
3218 Set_Standard_Error;
3220 E := First_Error_Msg;
3222 -- Find first printable message
3224 while E /= No_Error_Msg and then Errors.Table (E).Deleted loop
3225 E := Errors.Table (E).Next;
3226 end loop;
3228 Write_Char ('[');
3230 if E /= No_Error_Msg then
3232 Output_JSON_Message (E);
3234 E := Errors.Table (E).Next;
3236 while E /= No_Error_Msg loop
3238 -- Skip deleted messages.
3239 -- Also skip continuation messages, as they have already been
3240 -- printed along the message they're attached to.
3242 if not Errors.Table (E).Deleted
3243 and then not Errors.Table (E).Msg_Cont
3244 then
3245 Write_Char (',');
3246 Output_JSON_Message (E);
3247 end if;
3249 E := Errors.Table (E).Next;
3250 end loop;
3251 end if;
3253 Write_Char (']');
3255 Set_Standard_Output;
3257 -- Do not print any messages if all messages are killed -gnatdK
3259 elsif Debug_Flag_KK then
3261 null;
3263 -- Brief Error mode
3265 elsif Brief_Output or (not Full_List and not Verbose_Mode) then
3267 -- Use updated diagnostic mechanism
3269 if Debug_Flag_Underscore_DD then
3270 Convert_Errors_To_Diagnostics;
3272 Emit_Diagnostics;
3273 else
3274 Emit_Error_Msgs;
3275 end if;
3276 end if;
3278 -- Full source listing case
3280 if Full_List then
3281 List_Pragmas_Index := 1;
3282 List_Pragmas_Mode := True;
3283 E := First_Error_Msg;
3285 -- Normal case, to stdout (copyright notice already output)
3287 if Full_List_File_Name = null then
3288 if not Debug_Flag_7 then
3289 Write_Eol;
3290 end if;
3292 -- Output to file
3294 else
3295 Create_List_File_Access.all (Full_List_File_Name.all);
3296 Set_Special_Output (Write_List_Info_Access.all'Access);
3298 -- Write copyright notice to file
3300 if not Debug_Flag_7 then
3301 Write_Str ("GNAT ");
3302 Write_Str (Gnat_Version_String);
3303 Write_Eol;
3304 Write_Str ("Copyright 1992-" &
3305 Current_Year &
3306 ", Free Software Foundation, Inc.");
3307 Write_Eol;
3308 end if;
3309 end if;
3311 -- First list extended main source file units with errors
3313 for U in Main_Unit .. Last_Unit loop
3314 if In_Extended_Main_Source_Unit (Cunit_Entity (U))
3316 -- If debug flag d.m is set, only the main source is listed
3318 and then (U = Main_Unit or else not Debug_Flag_Dot_M)
3320 -- If the unit of the entity does not come from source, it is
3321 -- an implicit subprogram declaration for a child subprogram.
3322 -- Do not emit errors for it, they are listed with the body.
3324 and then
3325 (No (Cunit_Entity (U))
3326 or else Comes_From_Source (Cunit_Entity (U))
3327 or else not Is_Subprogram (Cunit_Entity (U)))
3329 -- If the compilation unit associated with this unit does not
3330 -- come from source, it means it is an instantiation that should
3331 -- not be included in the source listing.
3333 and then Comes_From_Source (Cunit (U))
3334 then
3335 declare
3336 Sfile : constant Source_File_Index := Source_Index (U);
3338 begin
3339 Write_Eol;
3341 -- Only write the header if Sfile is known
3343 if Sfile > No_Source_File then
3344 Write_Header (Sfile);
3345 Write_Eol;
3346 end if;
3348 -- Normally, we don't want an "error messages from file"
3349 -- message when listing the entire file, so we set the
3350 -- current source file as the current error source file.
3351 -- However, the old style of doing things was to list this
3352 -- message if pragma Source_Reference is present, even for
3353 -- the main unit. Since the purpose of the -gnatd.m switch
3354 -- is to duplicate the old behavior, we skip the reset if
3355 -- this debug flag is set.
3357 if not Debug_Flag_Dot_M then
3358 Current_Error_Source_File := Sfile;
3359 end if;
3361 -- Only output the listing if Sfile is known, to avoid
3362 -- crashing the compiler.
3364 if Sfile > No_Source_File then
3365 for N in 1 .. Last_Source_Line (Sfile) loop
3366 while E /= No_Error_Msg
3367 and then Errors.Table (E).Deleted
3368 loop
3369 E := Errors.Table (E).Next;
3370 end loop;
3372 Err_Flag :=
3373 E /= No_Error_Msg
3374 and then Errors.Table (E).Line = N
3375 and then Errors.Table (E).Sfile = Sfile;
3377 Output_Source_Line (N, Sfile, Err_Flag);
3379 if Err_Flag then
3380 Output_Error_Msgs (E);
3382 if not Debug_Flag_2 then
3383 Write_Eol;
3384 end if;
3385 end if;
3386 end loop;
3387 end if;
3388 end;
3389 end if;
3390 end loop;
3392 -- Then output errors, if any, for subsidiary units not in the
3393 -- main extended unit.
3395 -- Note: if debug flag d.m set, include errors for any units other
3396 -- than the main unit in the extended source unit (e.g. spec and
3397 -- subunits for a body).
3399 while E /= No_Error_Msg
3400 and then (not In_Extended_Main_Source_Unit
3401 (Errors.Table (E).Sptr.Ptr)
3402 or else
3403 (Debug_Flag_Dot_M
3404 and then Get_Source_Unit
3405 (Errors.Table (E).Sptr.Ptr) /= Main_Unit))
3406 loop
3407 if Errors.Table (E).Deleted then
3408 E := Errors.Table (E).Next;
3410 else
3411 Write_Eol;
3412 Output_Source_Line
3413 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3414 Output_Error_Msgs (E);
3415 end if;
3416 end loop;
3418 -- If output to file, write extra copy of error summary to the
3419 -- output file, and then close it.
3421 if Full_List_File_Name /= null then
3422 Write_Error_Summary;
3423 Write_Max_Errors;
3424 Close_List_File_Access.all;
3425 Cancel_Special_Output;
3426 end if;
3427 end if;
3429 -- Verbose mode (error lines only with error flags). Normally this is
3430 -- ignored in full list mode, unless we are listing to a file, in which
3431 -- case we still generate -gnatv output to standard output.
3433 if Verbose_Mode
3434 and then (not Full_List or else Full_List_File_Name /= null)
3435 then
3436 Write_Eol;
3438 -- Output the header only when Main_Source_File is known
3440 if Main_Source_File > No_Source_File then
3441 Write_Header (Main_Source_File);
3442 end if;
3444 E := First_Error_Msg;
3446 -- Loop through error lines
3448 while E /= No_Error_Msg loop
3449 if Errors.Table (E).Deleted then
3450 E := Errors.Table (E).Next;
3451 else
3452 Write_Eol;
3453 Output_Source_Line
3454 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
3455 Output_Error_Msgs (E);
3456 end if;
3457 end loop;
3458 end if;
3460 -- Output error summary if verbose or full list mode
3462 if Verbose_Mode or else Full_List then
3463 Write_Error_Summary;
3464 end if;
3466 if not Opt.JSON_Output then
3467 Write_Max_Errors;
3468 end if;
3470 if Warning_Mode = Treat_As_Error then
3471 declare
3472 Compile_Time_Pragma_Warnings : constant Nat :=
3473 Count_Compile_Time_Pragma_Warnings;
3474 Total : constant Int := Total_Errors_Detected + Warnings_Detected
3475 - Compile_Time_Pragma_Warnings;
3476 -- We need to protect against a negative Total here, because
3477 -- if a pragma Compile_Time_Warning occurs in dead code, it
3478 -- gets counted in Compile_Time_Pragma_Warnings but not in
3479 -- Warnings_Detected.
3480 begin
3481 Total_Errors_Detected := Int'Max (Total, 0);
3482 Warnings_Detected := Compile_Time_Pragma_Warnings;
3483 end;
3484 end if;
3485 end Output_Messages;
3487 ------------------------
3488 -- Output_Source_Line --
3489 ------------------------
3491 procedure Output_Source_Line
3492 (L : Physical_Line_Number;
3493 Sfile : Source_File_Index;
3494 Errs : Boolean)
3496 S : Source_Ptr;
3497 C : Character;
3499 Line_Number_Output : Boolean := False;
3500 -- Set True once line number is output
3502 Empty_Line : Boolean := True;
3503 -- Set False if line includes at least one character
3505 begin
3506 if Sfile /= Current_Error_Source_File then
3507 Write_Str ("==============Error messages for ");
3509 case Sinput.File_Type (Sfile) is
3510 when Sinput.Src =>
3511 Write_Str ("source");
3513 when Sinput.Config =>
3514 Write_Str ("configuration pragmas");
3516 when Sinput.Def =>
3517 Write_Str ("symbol definition");
3519 when Sinput.Preproc =>
3520 Write_Str ("preprocessing data");
3521 end case;
3523 Write_Str (" file: ");
3524 Write_Name (Full_File_Name (Sfile));
3525 Write_Eol;
3527 if Num_SRef_Pragmas (Sfile) > 0 then
3528 Write_Str ("--------------Line numbers from file: ");
3529 Write_Name (Full_Ref_Name (Sfile));
3530 Write_Str (" (starting at line ");
3531 Write_Int (Int (First_Mapped_Line (Sfile)));
3532 Write_Char (')');
3533 Write_Eol;
3534 end if;
3536 Current_Error_Source_File := Sfile;
3537 end if;
3539 if Errs or List_Pragmas_Mode then
3540 Output_Line_Number (Physical_To_Logical (L, Sfile));
3541 Line_Number_Output := True;
3542 end if;
3544 S := Line_Start (L, Sfile);
3546 loop
3547 C := Source_Text (Sfile) (S);
3548 exit when C = ASCII.LF or else C = ASCII.CR or else C = EOF;
3550 -- Deal with matching entry in List_Pragmas table
3552 if Full_List
3553 and then List_Pragmas_Index <= List_Pragmas.Last
3554 and then S = List_Pragmas.Table (List_Pragmas_Index).Ploc
3555 then
3556 case List_Pragmas.Table (List_Pragmas_Index).Ptyp is
3557 when Page =>
3558 Write_Char (C);
3560 -- Ignore if on line with errors so that error flags
3561 -- get properly listed with the error line .
3563 if not Errs then
3564 Write_Char (ASCII.FF);
3565 end if;
3567 when List_On =>
3568 List_Pragmas_Mode := True;
3570 if not Line_Number_Output then
3571 Output_Line_Number (Physical_To_Logical (L, Sfile));
3572 Line_Number_Output := True;
3573 end if;
3575 Write_Char (C);
3577 when List_Off =>
3578 Write_Char (C);
3579 List_Pragmas_Mode := False;
3580 end case;
3582 List_Pragmas_Index := List_Pragmas_Index + 1;
3584 -- Normal case (no matching entry in List_Pragmas table)
3586 else
3587 if Errs or List_Pragmas_Mode then
3588 Write_Char (C);
3589 end if;
3590 end if;
3592 Empty_Line := False;
3593 S := S + 1;
3594 end loop;
3596 -- If we have output a source line, then add the line terminator, with
3597 -- training spaces preserved (so we output the line exactly as input).
3599 if Line_Number_Output then
3600 if Empty_Line then
3601 Write_Eol;
3602 else
3603 Write_Eol_Keep_Blanks;
3604 end if;
3605 end if;
3606 end Output_Source_Line;
3608 --------------------
3609 -- Paren_Required --
3610 --------------------
3612 function Paren_Required (N : Node_Id) return Boolean is
3613 begin
3614 -- In a qualifed_expression the expression part needs to be enclosed in
3615 -- parentheses.
3617 if Nkind (Parent (N)) = N_Qualified_Expression then
3618 return N = Expression (Parent (N));
3620 else
3621 return False;
3622 end if;
3623 end Paren_Required;
3625 -----------------------------
3626 -- Remove_Warning_Messages --
3627 -----------------------------
3629 procedure Remove_Warning_Messages (N : Node_Id) is
3631 function Check_For_Warning (N : Node_Id) return Traverse_Result;
3632 -- This function checks one node for a possible warning message
3634 procedure Check_All_Warnings is new Traverse_Proc (Check_For_Warning);
3635 -- This defines the traversal operation
3637 -----------------------
3638 -- Check_For_Warning --
3639 -----------------------
3641 function Check_For_Warning (N : Node_Id) return Traverse_Result is
3642 Loc : constant Source_Ptr := Sloc (N);
3643 E : Error_Msg_Id;
3645 function To_Be_Removed (E : Error_Msg_Id) return Boolean;
3646 -- Returns True for a message that is to be removed. Also adjusts
3647 -- warning count appropriately.
3649 -------------------
3650 -- To_Be_Removed --
3651 -------------------
3653 function To_Be_Removed (E : Error_Msg_Id) return Boolean is
3654 begin
3655 if E /= No_Error_Msg
3657 -- Don't remove if location does not match
3659 and then Errors.Table (E).Optr.Ptr = Loc
3661 -- Don't remove if not warning/info message. Note that we do
3662 -- not remove style messages here. They are warning messages
3663 -- but not ones we want removed in this context.
3665 and then (Errors.Table (E).Warn
3666 or else
3667 Errors.Table (E).Warn_Runtime_Raise)
3669 -- Don't remove unconditional messages
3671 and then not Errors.Table (E).Uncond
3672 then
3673 if Errors.Table (E).Warn then
3674 Warnings_Detected := Warnings_Detected - 1;
3675 end if;
3677 -- When warning about a runtime exception has been escalated
3678 -- into error, the starting message has increased the total
3679 -- errors counter, so here we decrease this counter.
3681 if Errors.Table (E).Warn_Runtime_Raise
3682 and then not Errors.Table (E).Msg_Cont
3683 and then Warning_Mode = Treat_Run_Time_Warnings_As_Errors
3684 then
3685 Total_Errors_Detected := Total_Errors_Detected - 1;
3686 end if;
3688 return True;
3690 -- No removal required
3692 else
3693 return False;
3694 end if;
3695 end To_Be_Removed;
3697 -- Start of processing for Check_For_Warnings
3699 begin
3700 while To_Be_Removed (First_Error_Msg) loop
3701 First_Error_Msg := Errors.Table (First_Error_Msg).Next;
3702 end loop;
3704 if First_Error_Msg = No_Error_Msg then
3705 Last_Error_Msg := No_Error_Msg;
3706 end if;
3708 E := First_Error_Msg;
3709 while E /= No_Error_Msg loop
3710 while To_Be_Removed (Errors.Table (E).Next) loop
3711 Errors.Table (E).Next :=
3712 Errors.Table (Errors.Table (E).Next).Next;
3714 if Errors.Table (E).Next = No_Error_Msg then
3715 Last_Error_Msg := E;
3716 end if;
3717 end loop;
3719 E := Errors.Table (E).Next;
3720 end loop;
3722 -- Warnings may have been posted on subexpressions of original tree
3724 if Nkind (N) = N_Raise_Constraint_Error
3725 and then Is_Rewrite_Substitution (N)
3726 and then No (Condition (N))
3727 then
3728 Check_All_Warnings (Original_Node (N));
3729 end if;
3731 return OK;
3732 end Check_For_Warning;
3734 -- Start of processing for Remove_Warning_Messages
3736 begin
3737 if Warnings_Detected /= 0 then
3738 Check_All_Warnings (N);
3739 end if;
3740 end Remove_Warning_Messages;
3742 procedure Remove_Warning_Messages (L : List_Id) is
3743 Stat : Node_Id;
3744 begin
3745 Stat := First (L);
3746 while Present (Stat) loop
3747 Remove_Warning_Messages (Stat);
3748 Next (Stat);
3749 end loop;
3750 end Remove_Warning_Messages;
3752 ----------------------
3753 -- Adjust_Name_Case --
3754 ----------------------
3756 procedure Adjust_Name_Case
3757 (Buf : in out Bounded_String;
3758 Loc : Source_Ptr)
3760 Src_Ind : constant Source_File_Index := Get_Source_File_Index (Loc);
3761 Sbuffer : Source_Buffer_Ptr;
3762 Ref_Ptr : Integer;
3763 Src_Ptr : Source_Ptr;
3765 begin
3766 -- We have an all lower case name from Namet, and now we want to set
3767 -- the appropriate case. If possible we copy the actual casing from
3768 -- the source. If not we use standard identifier casing.
3770 Ref_Ptr := 1;
3771 Src_Ptr := Loc;
3773 -- For standard locations, always use mixed case
3775 if Loc <= No_Location then
3776 Set_Casing (Buf, Mixed_Case);
3778 else
3779 -- Determine if the reference we are dealing with corresponds to text
3780 -- at the point of the error reference. This will often be the case
3781 -- for simple identifier references, and is the case where we can
3782 -- copy the casing from the source.
3784 Sbuffer := Source_Text (Src_Ind);
3786 while Ref_Ptr <= Buf.Length loop
3787 exit when
3788 Fold_Lower (Sbuffer (Src_Ptr)) /=
3789 Fold_Lower (Buf.Chars (Ref_Ptr));
3790 Ref_Ptr := Ref_Ptr + 1;
3791 Src_Ptr := Src_Ptr + 1;
3792 end loop;
3794 -- If we get through the loop without a mismatch, then output the
3795 -- name the way it is cased in the source program.
3797 if Ref_Ptr > Buf.Length then
3798 Src_Ptr := Loc;
3800 for J in 1 .. Buf.Length loop
3801 Buf.Chars (J) := Sbuffer (Src_Ptr);
3802 Src_Ptr := Src_Ptr + 1;
3803 end loop;
3805 -- Otherwise set the casing using the default identifier casing
3807 else
3808 Set_Casing (Buf, Identifier_Casing (Src_Ind));
3809 end if;
3810 end if;
3811 end Adjust_Name_Case;
3813 ---------------------------
3814 -- Set_Identifier_Casing --
3815 ---------------------------
3817 procedure Set_Identifier_Casing
3818 (Identifier_Name : System.Address;
3819 File_Name : System.Address)
3821 Ident : constant Big_String_Ptr := To_Big_String_Ptr (Identifier_Name);
3822 File : constant Big_String_Ptr := To_Big_String_Ptr (File_Name);
3823 Flen : Natural;
3825 Desired_Case : Casing_Type := Mixed_Case;
3826 -- Casing required for result. Default value of Mixed_Case is used if
3827 -- for some reason we cannot find the right file name in the table.
3829 begin
3830 -- Get length of file name
3832 Flen := 0;
3833 while File (Flen + 1) /= ASCII.NUL loop
3834 Flen := Flen + 1;
3835 end loop;
3837 -- Loop through file names to find matching one. This is a bit slow, but
3838 -- we only do it in error situations so it is not so terrible. Note that
3839 -- if the loop does not exit, then the desired case will be left set to
3840 -- Mixed_Case, this can happen if the name was not in canonical form.
3842 for J in 1 .. Last_Source_File loop
3843 Get_Name_String (Full_Debug_Name (J));
3845 if Name_Len = Flen
3846 and then Name_Buffer (1 .. Name_Len) = String (File (1 .. Flen))
3847 then
3848 Desired_Case := Identifier_Casing (J);
3849 exit;
3850 end if;
3851 end loop;
3853 -- Copy identifier as given to Name_Buffer
3855 for J in Name_Buffer'Range loop
3856 Name_Buffer (J) := Ident (J);
3858 if Name_Buffer (J) = ASCII.NUL then
3859 Name_Len := J - 1;
3860 exit;
3861 end if;
3862 end loop;
3864 Set_Casing (Desired_Case);
3865 end Set_Identifier_Casing;
3867 -----------------------
3868 -- Set_Ignore_Errors --
3869 -----------------------
3871 procedure Set_Ignore_Errors (To : Boolean) is
3872 begin
3873 Errors_Must_Be_Ignored := To;
3874 end Set_Ignore_Errors;
3876 ------------------------------
3877 -- Set_Msg_Insertion_Column --
3878 ------------------------------
3880 procedure Set_Msg_Insertion_Column is
3881 begin
3882 if RM_Column_Check then
3883 Set_Msg_Str (" in column ");
3884 Set_Msg_Int (Int (Error_Msg_Col) + 1);
3885 end if;
3886 end Set_Msg_Insertion_Column;
3888 ----------------------------
3889 -- Set_Msg_Insertion_Node --
3890 ----------------------------
3892 procedure Set_Msg_Insertion_Node is
3893 pragma Assert (Present (Error_Msg_Node_1));
3894 K : Node_Kind;
3896 begin
3897 Suppress_Message := Error_Msg_Node_1 in Error | Any_Type;
3899 if Error_Msg_Node_1 = Error then
3900 Set_Msg_Blank;
3901 Set_Msg_Str ("<error>");
3903 elsif Error_Msg_Node_1 = Standard_Void_Type then
3904 Set_Msg_Blank;
3905 Set_Msg_Str ("procedure name");
3907 elsif Nkind (Error_Msg_Node_1) in N_Entity
3908 and then Ekind (Error_Msg_Node_1) = E_Anonymous_Access_Subprogram_Type
3909 then
3910 Set_Msg_Blank;
3911 Set_Msg_Str ("access to subprogram");
3913 else
3914 Set_Msg_Blank_Conditional;
3916 -- Output name
3918 K := Nkind (Error_Msg_Node_1);
3920 -- Skip quotes in the operator case, because the operator will supply
3921 -- the required quotes.
3923 if K in N_Op | N_Operator_Symbol | N_Defining_Operator_Symbol
3924 or else (K in N_Identifier | N_Defining_Identifier
3925 and then Is_Operator_Name (Chars (Error_Msg_Node_1)))
3926 then
3927 Set_Msg_Node (Error_Msg_Node_1);
3929 -- Normal case, not an operator, surround with quotes
3931 else
3932 Set_Msg_Quote;
3933 Set_Qualification (Error_Msg_Qual_Level, Error_Msg_Node_1);
3934 Set_Msg_Node (Error_Msg_Node_1);
3935 Set_Msg_Quote;
3936 end if;
3937 end if;
3939 -- The following assignment ensures that further ampersand insertion
3940 -- characters will correspond to the Error_Msg_Node_# parameter.
3942 Error_Msg_Node_1 := Error_Msg_Node_2;
3943 Error_Msg_Node_2 := Error_Msg_Node_3;
3944 Error_Msg_Node_3 := Error_Msg_Node_4;
3945 Error_Msg_Node_4 := Error_Msg_Node_5;
3946 Error_Msg_Node_5 := Error_Msg_Node_6;
3947 end Set_Msg_Insertion_Node;
3949 --------------------------------------
3950 -- Set_Msg_Insertion_Type_Reference --
3951 --------------------------------------
3953 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr) is
3954 Ent : Entity_Id;
3956 begin
3957 Set_Msg_Blank;
3959 if Error_Msg_Node_1 = Standard_Void_Type then
3960 Set_Msg_Str ("package or procedure name");
3961 return;
3963 elsif Error_Msg_Node_1 = Standard_Exception_Type then
3964 Set_Msg_Str ("exception name");
3965 return;
3967 elsif Error_Msg_Node_1 = Any_Array
3968 or else Error_Msg_Node_1 = Any_Boolean
3969 or else Error_Msg_Node_1 = Any_Character
3970 or else Error_Msg_Node_1 = Any_Composite
3971 or else Error_Msg_Node_1 = Any_Discrete
3972 or else Error_Msg_Node_1 = Any_Fixed
3973 or else Error_Msg_Node_1 = Any_Integer
3974 or else Error_Msg_Node_1 = Any_Modular
3975 or else Error_Msg_Node_1 = Any_Numeric
3976 or else Error_Msg_Node_1 = Any_Real
3977 or else Error_Msg_Node_1 = Any_Scalar
3978 or else Error_Msg_Node_1 = Any_String
3979 then
3980 Get_Unqualified_Decoded_Name_String (Chars (Error_Msg_Node_1));
3981 Set_Msg_Name_Buffer;
3982 return;
3984 elsif Error_Msg_Node_1 = Universal_Integer then
3985 Set_Msg_Str ("type universal integer");
3986 return;
3988 elsif Error_Msg_Node_1 = Universal_Real then
3989 Set_Msg_Str ("type universal real");
3990 return;
3992 elsif Error_Msg_Node_1 = Universal_Fixed then
3993 Set_Msg_Str ("type universal fixed");
3994 return;
3996 elsif Error_Msg_Node_1 = Universal_Access then
3997 Set_Msg_Str ("type universal access");
3998 return;
3999 end if;
4001 -- Special case of anonymous array
4003 if Nkind (Error_Msg_Node_1) in N_Entity
4004 and then Is_Array_Type (Error_Msg_Node_1)
4005 and then Present (Related_Array_Object (Error_Msg_Node_1))
4006 then
4007 Set_Msg_Str ("type of ");
4008 Set_Msg_Node (Related_Array_Object (Error_Msg_Node_1));
4009 Set_Msg_Str (" declared");
4010 Set_Msg_Insertion_Line_Number
4011 (Sloc (Related_Array_Object (Error_Msg_Node_1)), Flag);
4012 return;
4013 end if;
4015 -- If we fall through, it is not a special case, so first output
4016 -- the name of the type, preceded by private for a private type
4018 if Is_Private_Type (Error_Msg_Node_1) then
4019 Set_Msg_Str ("private type ");
4020 else
4021 Set_Msg_Str ("type ");
4022 end if;
4024 Ent := Error_Msg_Node_1;
4026 if Is_Internal_Name (Chars (Ent)) then
4027 Unwind_Internal_Type (Ent);
4028 end if;
4030 -- Types in Standard are displayed as "Standard.name"
4032 if Sloc (Ent) <= Standard_Location then
4033 Set_Msg_Quote;
4034 Set_Msg_Str ("Standard.");
4035 Set_Msg_Node (Ent);
4036 Add_Class;
4037 Set_Msg_Quote;
4039 -- Types in other language defined units are displayed as
4040 -- "package-name.type-name"
4042 elsif Is_Predefined_Unit (Get_Source_Unit (Ent)) then
4043 Get_Unqualified_Decoded_Name_String
4044 (Unit_Name (Get_Source_Unit (Ent)));
4045 Name_Len := Name_Len - 2;
4046 Set_Msg_Blank_Conditional;
4047 Set_Msg_Quote;
4048 Set_Casing (Mixed_Case);
4049 Set_Msg_Name_Buffer;
4050 Set_Msg_Char ('.');
4051 Set_Casing (Mixed_Case);
4052 Set_Msg_Node (Ent);
4053 Add_Class;
4054 Set_Msg_Quote;
4056 -- All other types display as "type name" defined at line xxx
4057 -- possibly qualified if qualification is requested.
4059 else
4060 Set_Msg_Quote;
4061 Set_Qualification (Error_Msg_Qual_Level, Ent);
4062 Set_Msg_Node (Ent);
4063 Add_Class;
4065 -- If we did not print a name (e.g. in the case of an anonymous
4066 -- subprogram type), there is no name to print, so remove quotes.
4068 if Buffer_Ends_With ('"') then
4069 Buffer_Remove ('"');
4070 else
4071 Set_Msg_Quote;
4072 end if;
4073 end if;
4075 -- If the original type did not come from a predefined file, add the
4076 -- location where the type was defined.
4078 if Sloc (Error_Msg_Node_1) > Standard_Location
4079 and then
4080 not Is_Predefined_Unit (Get_Source_Unit (Error_Msg_Node_1))
4081 then
4082 Get_Name_String (Unit_File_Name (Get_Source_Unit (Error_Msg_Node_1)));
4083 Set_Msg_Str (" defined");
4084 Set_Msg_Insertion_Line_Number (Sloc (Error_Msg_Node_1), Flag);
4086 -- If it did come from a predefined file, deal with the case where
4087 -- this was a file with a generic instantiation from elsewhere.
4089 else
4090 if Sloc (Error_Msg_Node_1) > Standard_Location then
4091 declare
4092 Iloc : constant Source_Ptr :=
4093 Instantiation_Location (Sloc (Error_Msg_Node_1));
4095 begin
4096 if Iloc /= No_Location
4097 and then not Suppress_Instance_Location
4098 then
4099 Set_Msg_Str (" from instance");
4100 Set_Msg_Insertion_Line_Number (Iloc, Flag);
4101 end if;
4102 end;
4103 end if;
4104 end if;
4105 end Set_Msg_Insertion_Type_Reference;
4107 ---------------------------------
4108 -- Set_Msg_Insertion_Unit_Name --
4109 ---------------------------------
4111 procedure Set_Msg_Insertion_Unit_Name (Suffix : Boolean := True) is
4112 begin
4113 if Error_Msg_Unit_1 = No_Unit_Name then
4114 null;
4116 elsif Error_Msg_Unit_1 = Error_Unit_Name then
4117 Set_Msg_Blank;
4118 Set_Msg_Str ("<error>");
4120 else
4121 Get_Unit_Name_String (Global_Name_Buffer, Error_Msg_Unit_1, Suffix);
4122 Set_Msg_Blank;
4123 Set_Msg_Quote;
4124 Set_Msg_Name_Buffer;
4125 Set_Msg_Quote;
4126 end if;
4128 -- The following assignment ensures that a second percent insertion
4129 -- character will correspond to the Error_Msg_Unit_2 parameter.
4131 Error_Msg_Unit_1 := Error_Msg_Unit_2;
4132 end Set_Msg_Insertion_Unit_Name;
4134 ------------------
4135 -- Set_Msg_Node --
4136 ------------------
4138 procedure Set_Msg_Node (Node : Node_Id) is
4139 Loc : Source_Ptr;
4140 Ent : Entity_Id;
4141 Nam : Name_Id;
4143 begin
4144 case Nkind (Node) is
4145 when N_Designator =>
4146 Set_Msg_Node (Name (Node));
4147 Set_Msg_Char ('.');
4148 Set_Msg_Node (Identifier (Node));
4149 return;
4151 when N_Defining_Program_Unit_Name =>
4152 Set_Msg_Node (Name (Node));
4153 Set_Msg_Char ('.');
4154 Set_Msg_Node (Defining_Identifier (Node));
4155 return;
4157 when N_Expanded_Name
4158 | N_Selected_Component
4160 Set_Msg_Node (Prefix (Node));
4161 Set_Msg_Char ('.');
4162 Set_Msg_Node (Selector_Name (Node));
4163 return;
4165 when others =>
4166 null;
4167 end case;
4169 -- The only remaining possibilities are identifiers, defining
4170 -- identifiers, pragmas, and pragma argument associations.
4172 if Nkind (Node) = N_Pragma then
4173 Nam := Pragma_Name (Node);
4174 Loc := Sloc (Node);
4176 -- The other cases have Chars fields
4178 -- First deal with internal names, which generally represent something
4179 -- gone wrong. First attempt: if this is a rewritten node that rewrites
4180 -- something with a Chars field that is not an internal name, use that.
4182 elsif Is_Internal_Name (Chars (Node))
4183 and then Nkind (Original_Node (Node)) in N_Has_Chars
4184 and then not Is_Internal_Name (Chars (Original_Node (Node)))
4185 then
4186 Nam := Chars (Original_Node (Node));
4187 Loc := Sloc (Original_Node (Node));
4189 -- Another shot for internal names, in the case of internal type names,
4190 -- we try to find a reasonable representation for the external name.
4192 elsif Is_Internal_Name (Chars (Node))
4193 and then
4194 ((Is_Entity_Name (Node)
4195 and then Present (Entity (Node))
4196 and then Is_Type (Entity (Node)))
4197 or else
4198 (Nkind (Node) = N_Defining_Identifier and then Is_Type (Node)))
4199 then
4200 if Nkind (Node) = N_Identifier then
4201 Ent := Entity (Node);
4202 else
4203 Ent := Node;
4204 end if;
4206 Loc := Sloc (Ent);
4208 -- If the type is the designated type of an access_to_subprogram,
4209 -- then there is no name to provide in the call.
4211 if Ekind (Ent) = E_Subprogram_Type then
4212 return;
4214 -- Otherwise, we will be able to find some kind of name to output
4216 else
4217 Unwind_Internal_Type (Ent);
4218 Nam := Chars (Ent);
4219 end if;
4221 -- If not internal name, or if we could not find a reasonable possible
4222 -- substitution for the internal name, just use name in Chars field.
4224 else
4225 Nam := Chars (Node);
4226 Loc := Sloc (Node);
4227 end if;
4229 -- At this stage, the name to output is in Nam
4231 Get_Unqualified_Decoded_Name_String (Nam);
4233 -- Remove trailing upper case letters from the name (useful for
4234 -- dealing with some cases of internal names).
4236 while Name_Len > 1 and then Name_Buffer (Name_Len) in 'A' .. 'Z' loop
4237 Name_Len := Name_Len - 1;
4238 end loop;
4240 -- If we have any of the names from standard that start with the
4241 -- characters "any " (e.g. Any_Type), then kill the message since
4242 -- almost certainly it is a junk cascaded message.
4244 if Name_Len > 4
4245 and then Name_Buffer (1 .. 4) = "any "
4246 then
4247 Kill_Message := True;
4248 end if;
4250 -- If we still have an internal name, kill the message (will only
4251 -- work if we already had errors!)
4253 if Is_Internal_Name then
4254 Kill_Message := True;
4255 end if;
4256 -- Remaining step is to adjust casing and possibly add 'Class
4258 Adjust_Name_Case (Global_Name_Buffer, Loc);
4259 Set_Msg_Name_Buffer;
4260 Add_Class;
4261 end Set_Msg_Node;
4263 ------------------
4264 -- Set_Msg_Text --
4265 ------------------
4267 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is
4268 C : Character; -- Current character
4269 P : Natural; -- Current index;
4271 procedure Skip_Msg_Insertion_Warning (C : Character);
4272 -- Skip the ? ?? ?x? ?*? ?$? insertion sequences (and the same
4273 -- sequences using < instead of ?). The caller has already bumped
4274 -- the pointer past the initial ? or < and C is set to this initial
4275 -- character (? or <). This procedure skips past the rest of the
4276 -- sequence. We do not need to set Msg_Insertion_Char, since this
4277 -- was already done during the message prescan.
4278 -- No validity check is performed as the insertion sequence is
4279 -- supposed to be sane. See Prescan_Message.Parse_Message_Class in
4280 -- erroutc.adb for the validity checks.
4282 --------------------------------
4283 -- Skip_Msg_Insertion_Warning --
4284 --------------------------------
4286 procedure Skip_Msg_Insertion_Warning (C : Character) is
4287 begin
4288 if P <= Text'Last and then Text (P) = C then
4289 P := P + 1;
4291 elsif P < Text'Last and then Text (P + 1) = C
4292 and then Text (P) in 'a' .. 'z' | 'A' .. 'Z' |
4293 '0' .. '9' | '*' | '$'
4294 then
4295 P := P + 2;
4297 elsif P + 1 < Text'Last and then Text (P + 2) = C
4298 and then Text (P) in '.' | '_'
4299 and then Text (P + 1) in 'a' .. 'z'
4300 then
4301 P := P + 3;
4302 end if;
4303 end Skip_Msg_Insertion_Warning;
4305 -- Start of processing for Set_Msg_Text
4307 begin
4308 Manual_Quote_Mode := False;
4309 Msglen := 0;
4310 Flag_Source := Get_Source_File_Index (Flag);
4312 -- Skip info: at start, we have recorded this in Is_Info_Msg, and this
4313 -- will be used (Info field in error message object) to put back the
4314 -- string when it is printed. We need to do this, or we get confused
4315 -- with instantiation continuations.
4317 if Text'Length > 6
4318 and then Text (Text'First .. Text'First + 5) = "info: "
4319 then
4320 P := Text'First + 6;
4321 else
4322 P := Text'First;
4323 end if;
4325 -- Loop through characters of message
4327 while P <= Text'Last loop
4328 C := Text (P);
4329 P := P + 1;
4331 -- Check for insertion character or sequence
4333 case C is
4334 when '%' =>
4335 if P <= Text'Last and then Text (P) = '%' then
4336 P := P + 1;
4337 Set_Msg_Insertion_Name_Literal;
4338 else
4339 Set_Msg_Insertion_Name;
4340 end if;
4342 when '$' =>
4343 if P <= Text'Last and then Text (P) = '$' then
4344 P := P + 1;
4345 Set_Msg_Insertion_Unit_Name (Suffix => False);
4346 else
4347 Set_Msg_Insertion_Unit_Name;
4348 end if;
4350 when '{' =>
4351 Set_Msg_Insertion_File_Name;
4353 when '}' =>
4354 Set_Msg_Insertion_Type_Reference (Flag);
4356 when '*' =>
4357 Set_Msg_Insertion_Reserved_Name;
4359 when '&' =>
4360 Set_Msg_Insertion_Node;
4362 when '#' =>
4363 Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag);
4365 when '\' =>
4366 Continuation := True;
4368 if P <= Text'Last and then Text (P) = '\' then
4369 Continuation_New_Line := True;
4370 P := P + 1;
4371 end if;
4373 when '@' =>
4374 Set_Msg_Insertion_Column;
4376 when '>' =>
4377 Set_Msg_Insertion_Run_Time_Name;
4379 when '^' =>
4380 Set_Msg_Insertion_Uint;
4382 when '`' =>
4383 Manual_Quote_Mode := not Manual_Quote_Mode;
4384 Set_Msg_Char ('"');
4386 when '!' =>
4387 null; -- already dealt with
4389 when '?' =>
4390 Skip_Msg_Insertion_Warning ('?');
4392 when '<' =>
4393 Skip_Msg_Insertion_Warning ('<');
4395 when '|' =>
4396 null; -- already dealt with
4398 when ''' =>
4399 Set_Msg_Char (Text (P));
4400 P := P + 1;
4402 when '~' =>
4403 Set_Msg_Str (Error_Msg_String (1 .. Error_Msg_Strlen));
4405 -- Upper case letter
4407 when 'A' .. 'Z' =>
4409 -- Start of reserved word if two or more
4411 if P <= Text'Last and then Text (P) in 'A' .. 'Z' then
4412 P := P - 1;
4413 Set_Msg_Insertion_Reserved_Word (Text, P);
4415 -- Single upper case letter is just inserted
4417 else
4418 Set_Msg_Char (C);
4419 end if;
4421 -- '[' (will be/would have been raised at run time)
4423 when '[' =>
4425 -- "[]" (insertion of error code)
4427 if P <= Text'Last and then Text (P) = ']' then
4428 P := P + 1;
4429 Set_Msg_Insertion_Code;
4431 else
4432 -- Switch the message from a warning to an error if the flag
4433 -- -gnatwE is specified to treat run-time exception warnings
4434 -- as errors.
4436 if Is_Warning_Msg
4437 and then Warning_Mode = Treat_Run_Time_Warnings_As_Errors
4438 then
4439 Is_Warning_Msg := False;
4440 Is_Runtime_Raise := True;
4441 end if;
4443 if Is_Warning_Msg then
4444 Set_Msg_Str ("will be raised at run time");
4445 else
4446 Set_Msg_Str ("would have been raised at run time");
4447 end if;
4448 end if;
4450 -- ']' (may be/might have been raised at run time)
4452 when ']' =>
4453 if Is_Warning_Msg then
4454 Set_Msg_Str ("may be raised at run time");
4455 else
4456 Set_Msg_Str ("might have been raised at run time");
4457 end if;
4459 -- Normal character with no special treatment
4461 when others =>
4462 Set_Msg_Char (C);
4463 end case;
4464 end loop;
4465 end Set_Msg_Text;
4467 ----------------
4468 -- Set_Posted --
4469 ----------------
4471 procedure Set_Posted (N : Node_Id) is
4472 P : Node_Id;
4474 begin
4475 if Is_Serious_Error then
4477 -- We always set Error_Posted on the node itself
4479 Set_Error_Posted (N);
4481 -- If it is a subexpression, then set Error_Posted on parents up to
4482 -- and including the first non-subexpression construct. This helps
4483 -- avoid cascaded error messages within a single expression.
4485 P := N;
4486 loop
4487 P := Parent (P);
4488 exit when No (P);
4489 Set_Error_Posted (P);
4490 exit when Nkind (P) not in N_Subexpr;
4491 end loop;
4493 if Nkind (P) in N_Pragma_Argument_Association
4494 | N_Component_Association
4495 | N_Discriminant_Association
4496 | N_Generic_Association
4497 | N_Parameter_Association
4498 then
4499 Set_Error_Posted (Parent (P));
4500 end if;
4502 -- A special check, if we just posted an error on an attribute
4503 -- definition clause, then also set the entity involved as posted.
4504 -- For example, this stops complaining about the alignment after
4505 -- complaining about the size, which is likely to be useless.
4507 if Nkind (P) = N_Attribute_Definition_Clause then
4508 if Is_Entity_Name (Name (P)) then
4509 Set_Error_Posted (Entity (Name (P)));
4510 end if;
4511 end if;
4512 end if;
4513 end Set_Posted;
4515 -----------------------
4516 -- Set_Qualification --
4517 -----------------------
4519 procedure Set_Qualification (N : Nat; E : Entity_Id) is
4520 begin
4521 if N /= 0 and then Scope (E) /= Standard_Standard then
4522 Set_Qualification (N - 1, Scope (E));
4523 Set_Msg_Node (Scope (E));
4524 Set_Msg_Char ('.');
4525 end if;
4526 end Set_Qualification;
4528 -------------------------------------
4529 -- Should_Ignore_Pragma_SPARK_Mode --
4530 -------------------------------------
4532 function Should_Ignore_Pragma_SPARK_Mode return Boolean is
4533 begin
4534 return Get_Name_Table_Boolean3 (Name_SPARK_Mode);
4535 end Should_Ignore_Pragma_SPARK_Mode;
4537 ------------------------
4538 -- Special_Msg_Delete --
4539 ------------------------
4541 -- Is it really right to have all this specialized knowledge in errout?
4543 function Special_Msg_Delete
4544 (Msg : String;
4545 N : Node_Or_Entity_Id;
4546 E : Node_Or_Entity_Id) return Boolean
4548 begin
4549 -- Never delete messages in -gnatdO mode
4551 if Debug_Flag_OO then
4552 return False;
4554 -- Processing for "Size too small" messages
4556 elsif Is_Size_Too_Small_Message (Msg) then
4558 -- Suppress "size too small" errors in CodePeer mode, since code may
4559 -- be analyzed in a different configuration than the one used for
4560 -- compilation. Even when the configurations match, this message
4561 -- may be issued on correct code, because pragma Pack is ignored
4562 -- in CodePeer mode.
4564 if CodePeer_Mode then
4565 return True;
4567 -- When a size is wrong for a frozen type there is no explicit size
4568 -- clause, and other errors have occurred, suppress the message,
4569 -- since it is likely that this size error is a cascaded result of
4570 -- other errors. The reason we eliminate unfrozen types is that
4571 -- messages issued before the freeze type are for sure OK.
4573 elsif Nkind (N) in N_Entity
4574 and then Is_Frozen (E)
4575 and then Serious_Errors_Detected > 0
4576 and then Nkind (N) /= N_Component_Clause
4577 and then Nkind (Parent (N)) /= N_Component_Clause
4578 and then
4579 No (Get_Attribute_Definition_Clause (E, Attribute_Size))
4580 and then
4581 No (Get_Attribute_Definition_Clause (E, Attribute_Object_Size))
4582 and then
4583 No (Get_Attribute_Definition_Clause (E, Attribute_Value_Size))
4584 then
4585 return True;
4586 end if;
4587 end if;
4589 -- All special tests complete, so go ahead with message
4591 return False;
4592 end Special_Msg_Delete;
4594 -----------------
4595 -- SPARK_Msg_N --
4596 -----------------
4598 procedure SPARK_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
4599 begin
4600 -- If SPARK_Mode is Off, we do not report SPARK legality errors to give
4601 -- the flexibility to opt out of SPARK checking completely. We do the
4602 -- same if pragma Ignore_Pragma (SPARK_Mode) was specified, as a way
4603 -- for tools to ignore SPARK checking even on SPARK code.
4605 if SPARK_Mode /= Off
4606 and then not Should_Ignore_Pragma_SPARK_Mode
4607 then
4608 Error_Msg_N (Msg, N);
4609 end if;
4610 end SPARK_Msg_N;
4612 ------------------
4613 -- SPARK_Msg_NE --
4614 ------------------
4616 procedure SPARK_Msg_NE
4617 (Msg : String;
4618 N : Node_Or_Entity_Id;
4619 E : Node_Or_Entity_Id)
4621 begin
4622 if SPARK_Mode /= Off
4623 and then not Should_Ignore_Pragma_SPARK_Mode
4624 then
4625 Error_Msg_NE (Msg, N, E);
4626 end if;
4627 end SPARK_Msg_NE;
4629 --------------------------
4630 -- Unwind_Internal_Type --
4631 --------------------------
4633 procedure Unwind_Internal_Type (Ent : in out Entity_Id) is
4634 Derived : Boolean := False;
4635 Mchar : Character;
4636 Old_Ent : Entity_Id;
4638 begin
4639 -- Undo placement of a quote, since we will put it back later
4641 Mchar := Msg_Buffer (Msglen);
4643 if Mchar = '"' then
4644 Msglen := Msglen - 1;
4645 end if;
4647 -- The loop here deals with recursive types, we are trying to find a
4648 -- related entity that is not an implicit type. Note that the check with
4649 -- Old_Ent stops us from getting "stuck". Also, we don't output the
4650 -- "type derived from" message more than once in the case where we climb
4651 -- up multiple levels.
4653 Find : loop
4654 Old_Ent := Ent;
4656 -- Implicit access type, use directly designated type In Ada 2005,
4657 -- the designated type may be an anonymous access to subprogram, in
4658 -- which case we can only point to its definition.
4660 if Is_Access_Type (Ent) then
4661 if Ekind (Ent) = E_Access_Subprogram_Type
4662 or else Ekind (Ent) = E_Anonymous_Access_Subprogram_Type
4663 or else Is_Access_Protected_Subprogram_Type (Ent)
4664 then
4665 Ent := Directly_Designated_Type (Ent);
4667 if not Comes_From_Source (Ent) then
4668 if Buffer_Ends_With ("type ") then
4669 Buffer_Remove ("type ");
4670 end if;
4671 end if;
4673 if Ekind (Ent) = E_Function then
4674 Set_Msg_Str ("access to function ");
4675 elsif Ekind (Ent) = E_Procedure then
4676 Set_Msg_Str ("access to procedure ");
4677 else
4678 Set_Msg_Str ("access to subprogram");
4679 end if;
4681 exit Find;
4683 -- Type is access to object, named or anonymous
4685 else
4686 Set_Msg_Str ("access to ");
4687 Ent := Directly_Designated_Type (Ent);
4688 end if;
4690 -- Classwide type
4692 elsif Is_Class_Wide_Type (Ent) then
4693 Class_Flag := True;
4694 Ent := Root_Type (Ent);
4696 -- Use base type if this is a subtype
4698 elsif Ent /= Base_Type (Ent) then
4699 Buffer_Remove ("type ");
4701 -- Avoid duplication "subtype of subtype of", and also replace
4702 -- "derived from subtype of" simply by "derived from"
4704 if not Buffer_Ends_With ("subtype of ")
4705 and then not Buffer_Ends_With ("derived from ")
4706 then
4707 Set_Msg_Str ("subtype of ");
4708 end if;
4710 Ent := Base_Type (Ent);
4712 -- If this is a base type with a first named subtype, use the first
4713 -- named subtype instead. This is not quite accurate in all cases,
4714 -- but it makes too much noise to be accurate and add 'Base in all
4715 -- cases. Note that we only do this is the first named subtype is not
4716 -- itself an internal name. This avoids the obvious loop (subtype ->
4717 -- basetype -> subtype) which would otherwise occur).
4719 else
4720 declare
4721 FST : constant Entity_Id := First_Subtype (Ent);
4723 begin
4724 if not Is_Internal_Name (Chars (FST)) then
4725 Ent := FST;
4726 exit Find;
4728 -- Otherwise use root type
4730 else
4731 if not Derived then
4732 Buffer_Remove ("type ");
4734 -- Test for "subtype of type derived from" which seems
4735 -- excessive and is replaced by "type derived from".
4737 Buffer_Remove ("subtype of");
4739 -- Avoid duplicated "type derived from type derived from"
4741 if not Buffer_Ends_With ("type derived from ") then
4742 Set_Msg_Str ("type derived from ");
4743 end if;
4745 Derived := True;
4746 end if;
4747 end if;
4748 end;
4750 Ent := Etype (Ent);
4751 end if;
4753 -- If we are stuck in a loop, get out and settle for the internal
4754 -- name after all. In this case we set to kill the message if it is
4755 -- not the first error message (we really try hard not to show the
4756 -- dirty laundry of the implementation to the poor user).
4758 if Ent = Old_Ent then
4759 Kill_Message := True;
4760 exit Find;
4761 end if;
4763 -- Get out if we finally found a non-internal name to use
4765 exit Find when not Is_Internal_Name (Chars (Ent));
4766 end loop Find;
4768 if Mchar = '"' then
4769 Set_Msg_Char ('"');
4770 end if;
4771 end Unwind_Internal_Type;
4773 --------------------
4774 -- Warn_Insertion --
4775 --------------------
4777 function Warn_Insertion return String is
4778 begin
4779 if Warning_Msg_Char = "? " then
4780 return "??";
4781 elsif Warning_Msg_Char = " " then
4782 return "?";
4783 elsif Warning_Msg_Char (2) = ' ' then
4784 return '?' & Warning_Msg_Char (1) & '?';
4785 else
4786 return '?' & Warning_Msg_Char & '?';
4787 end if;
4788 end Warn_Insertion;
4790 end Errout;