* gcc.c-torture/execute/20020307-1.c: New test.
[official-gcc.git] / gcc / ada / errout.adb
blobe4576e64d50bc122b04dc90dce8144950ad71c04
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E R R O U T --
6 -- --
7 -- B o d y --
8 -- --
9 -- $Revision: 1.4 $
10 -- --
11 -- Copyright (C) 1992-2001 Free Software Foundation, Inc. --
12 -- --
13 -- GNAT is free software; you can redistribute it and/or modify it under --
14 -- terms of the GNU General Public License as published by the Free Soft- --
15 -- ware Foundation; either version 2, or (at your option) any later ver- --
16 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
19 -- for more details. You should have received a copy of the GNU General --
20 -- Public License distributed with GNAT; see file COPYING. If not, write --
21 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
22 -- MA 02111-1307, USA. --
23 -- --
24 -- GNAT was originally developed by the GNAT team at New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 -- --
27 ------------------------------------------------------------------------------
29 -- Warning! Error messages can be generated during Gigi processing by direct
30 -- calls to error message routines, so it is essential that the processing
31 -- in this body be consistent with the requirements for the Gigi processing
32 -- environment, and that in particular, no disallowed table expansion is
33 -- allowed to occur.
35 with Atree; use Atree;
36 with Casing; use Casing;
37 with Csets; use Csets;
38 with Debug; use Debug;
39 with Einfo; use Einfo;
40 with Fname; use Fname;
41 with Hostparm;
42 with Lib; use Lib;
43 with Namet; use Namet;
44 with Opt; use Opt;
45 with Output; use Output;
46 with Scans; use Scans;
47 with Sinput; use Sinput;
48 with Sinfo; use Sinfo;
49 with Snames; use Snames;
50 with Stand; use Stand;
51 with Style;
52 with Uintp; use Uintp;
53 with Uname; use Uname;
55 package body Errout is
57 Class_Flag : Boolean := False;
58 -- This flag is set True when outputting a reference to a class-wide
59 -- type, and is used by Add_Class to insert 'Class at the proper point
61 Continuation : Boolean;
62 -- Indicates if current message is a continuation. Initialized from the
63 -- Msg_Cont parameter in Error_Msg_Internal and then set True if a \
64 -- insertion character is encountered.
66 Cur_Msg : Error_Msg_Id;
67 -- Id of most recently posted error message
69 Flag_Source : Source_File_Index;
70 -- Source file index for source file where error is being posted
72 Is_Warning_Msg : Boolean;
73 -- Set by Set_Msg_Text to indicate if current message is warning message
75 Is_Unconditional_Msg : Boolean;
76 -- Set by Set_Msg_Text to indicate if current message is unconditional
78 Kill_Message : Boolean;
79 -- A flag used to kill weird messages (e.g. those containing uninterpreted
80 -- implicit type references) if we have already seen at least one message
81 -- already. The idea is that we hope the weird message is a junk cascaded
82 -- message that should be suppressed.
84 Last_Killed : Boolean := False;
85 -- Set True if the most recently posted non-continuation message was
86 -- killed. This is used to determine the processing of any continuation
87 -- messages that follow.
89 List_Pragmas_Index : Int;
90 -- Index into List_Pragmas table
92 List_Pragmas_Mode : Boolean;
93 -- Starts True, gets set False by pragma List (Off), True by List (On)
95 Manual_Quote_Mode : Boolean;
96 -- Set True in manual quotation mode
98 Max_Msg_Length : constant := 80 + 2 * Hostparm.Max_Line_Length;
99 -- Maximum length of error message. The addition of Max_Line_Length
100 -- ensures that two insertion tokens of maximum length can be accomodated.
102 Msg_Buffer : String (1 .. Max_Msg_Length);
103 -- Buffer used to prepare error messages
105 Msglen : Integer;
106 -- Number of characters currently stored in the message buffer
108 Suppress_Message : Boolean;
109 -- A flag used to suppress certain obviously redundant messages (i.e.
110 -- those referring to a node whose type is Any_Type). This suppression
111 -- is effective only if All_Errors_Mode is off.
113 Suppress_Instance_Location : Boolean := False;
114 -- Normally, if a # location in a message references a location within
115 -- a generic template, then a note is added giving the location of the
116 -- instantiation. If this variable is set True, then this note is not
117 -- output. This is used for internal processing for the case of an
118 -- illegal instantiation. See Error_Msg routine for further details.
120 -----------------------------------
121 -- Error Message Data Structures --
122 -----------------------------------
124 -- The error messages are stored as a linked list of error message objects
125 -- sorted into ascending order by the source location (Sloc). Each object
126 -- records the text of the message and its source location.
128 -- The following record type and table are used to represent error
129 -- messages, with one entry in the table being allocated for each message.
131 type Error_Msg_Object is record
132 Text : String_Ptr;
133 -- Text of error message, fully expanded with all insertions
135 Next : Error_Msg_Id;
136 -- Pointer to next message in error chain
138 Sfile : Source_File_Index;
139 -- Source table index of source file. In the case of an error that
140 -- refers to a template, always references the original template
141 -- not an instantiation copy.
143 Sptr : Source_Ptr;
144 -- Flag pointer. In the case of an error that refers to a template,
145 -- always references the original template, not an instantiation copy.
146 -- This value is the actual place in the source that the error message
147 -- will be posted.
149 Fptr : Source_Ptr;
150 -- Flag location used in the call to post the error. This is normally
151 -- the same as Sptr, except in the case of instantiations, where it
152 -- is the original flag location value. This may refer to an instance
153 -- when the actual message (and hence Sptr) references the template.
155 Line : Physical_Line_Number;
156 -- Line number for error message
158 Col : Column_Number;
159 -- Column number for error message
161 Warn : Boolean;
162 -- True if warning message (i.e. insertion character ? appeared)
164 Uncond : Boolean;
165 -- True if unconditional message (i.e. insertion character ! appeared)
167 Msg_Cont : Boolean;
168 -- This is used for logical messages that are composed of multiple
169 -- individual messages. For messages that are not part of such a
170 -- group, or that are the first message in such a group. Msg_Cont
171 -- is set to False. For subsequent messages in a group, Msg_Cont
172 -- is set to True. This is used to make sure that such a group of
173 -- messages is either suppressed or retained as a group (e.g. in
174 -- the circuit that deletes identical messages).
176 Deleted : Boolean;
177 -- If this flag is set, the message is not printed. This is used
178 -- in the circuit for deleting duplicate/redundant error messages.
179 end record;
181 package Errors is new Table.Table (
182 Table_Component_Type => Error_Msg_Object,
183 Table_Index_Type => Error_Msg_Id,
184 Table_Low_Bound => 1,
185 Table_Initial => 200,
186 Table_Increment => 200,
187 Table_Name => "Error");
189 Error_Msgs : Error_Msg_Id;
190 -- The list of error messages
192 --------------------------
193 -- Warning Mode Control --
194 --------------------------
196 -- Pragma Warnings allows warnings to be turned off for a specified
197 -- region of code, and the following tabl is the data structure used
198 -- to keep track of these regions.
200 -- It contains pairs of source locations, the first being the start
201 -- location for a warnings off region, and the second being the end
202 -- location. When a pragma Warnings (Off) is encountered, a new entry
203 -- is established extending from the location of the pragma to the
204 -- end of the current source file. A subsequent pragma Warnings (On)
205 -- adjusts the end point of this entry appropriately.
207 -- If all warnings are suppressed by comamnd switch, then there is a
208 -- dummy entry (put there by Errout.Initialize) at the start of the
209 -- table which covers all possible Source_Ptr values. Note that the
210 -- source pointer values in this table always reference the original
211 -- template, not an instantiation copy, in the generic case.
213 type Warnings_Entry is record
214 Start : Source_Ptr;
215 Stop : Source_Ptr;
216 end record;
218 package Warnings is new Table.Table (
219 Table_Component_Type => Warnings_Entry,
220 Table_Index_Type => Natural,
221 Table_Low_Bound => 1,
222 Table_Initial => 100,
223 Table_Increment => 200,
224 Table_Name => "Warnings");
226 -----------------------
227 -- Local Subprograms --
228 -----------------------
230 procedure Add_Class;
231 -- Add 'Class to buffer for class wide type case (Class_Flag set)
233 function Buffer_Ends_With (S : String) return Boolean;
234 -- Tests if message buffer ends with given string preceded by a space
236 procedure Buffer_Remove (S : String);
237 -- Removes given string from end of buffer if it is present
238 -- at end of buffer, and preceded by a space.
240 procedure Debug_Output (N : Node_Id);
241 -- Called from Error_Msg_N and Error_Msg_NE to generate line of debug
242 -- output giving node number (of node N) if the debug X switch is set.
244 procedure Check_Duplicate_Message (M1, M2 : Error_Msg_Id);
245 -- This function is passed the Id values of two error messages. If
246 -- either M1 or M2 is a continuation message, or is already deleted,
247 -- the call is ignored. Otherwise a check is made to see if M1 and M2
248 -- are duplicated or redundant. If so, the message to be deleted and
249 -- all its continuations are marked with the Deleted flag set to True.
251 procedure Error_Msg_Internal
252 (Msg : String;
253 Flag_Location : Source_Ptr;
254 Msg_Cont : Boolean);
255 -- This is like Error_Msg, except that Flag_Location is known not to be
256 -- a location within a instantiation of a generic template. The outer
257 -- level routine, Error_Msg, takes care of dealing with the generic case.
258 -- Msg_Cont is set True to indicate that the message is a continuation of
259 -- a previous message. This means that it must have the same Flag_Location
260 -- as the previous message.
262 procedure Set_Next_Non_Deleted_Msg (E : in out Error_Msg_Id);
263 -- Given a message id, move to next message id, but skip any deleted
264 -- messages, so that this results in E on output being the first non-
265 -- deleted message following the input value of E, or No_Error_Msg if
266 -- the input value of E was either already No_Error_Msg, or was the
267 -- last non-deleted message.
269 function No_Warnings (N : Node_Or_Entity_Id) return Boolean;
270 -- Determines if warnings should be suppressed for the given node
272 function OK_Node (N : Node_Id) return Boolean;
273 -- Determines if a node is an OK node to place an error message on (return
274 -- True) or if the error message should be suppressed (return False). A
275 -- message is suppressed if the node already has an error posted on it,
276 -- or if it refers to an Etype that has an error posted on it, or if
277 -- it references an Entity that has an error posted on it.
279 procedure Output_Error_Msgs (E : in out Error_Msg_Id);
280 -- Output source line, error flag, and text of stored error message and
281 -- all subsequent messages for the same line and unit. On return E is
282 -- set to be one higher than the last message output.
284 procedure Output_Line_Number (L : Logical_Line_Number);
285 -- Output a line number as six digits (with leading zeroes suppressed),
286 -- followed by a period and a blank (note that this is 8 characters which
287 -- means that tabs in the source line will not get messed up). Line numbers
288 -- that match or are less than the last Source_Reference pragma are listed
289 -- as all blanks, avoiding output of junk line numbers.
291 procedure Output_Msg_Text (E : Error_Msg_Id);
292 -- Outputs characters of text in the text of the error message E, excluding
293 -- any final exclamation point. Note that no end of line is output, the
294 -- caller is responsible for adding the end of line.
296 procedure Output_Source_Line
297 (L : Physical_Line_Number;
298 Sfile : Source_File_Index;
299 Errs : Boolean);
300 -- Outputs text of source line L, in file S, together with preceding line
301 -- number, as described above for Output_Line_Number. The Errs parameter
302 -- indicates if there are errors attached to the line, which forces
303 -- listing on, even in the presence of pragma List (Off).
305 function Same_Error (M1, M2 : Error_Msg_Id) return Boolean;
306 -- See if two messages have the same text. Returns true if the text
307 -- of the two messages is identical, or if one of them is the same
308 -- as the other with an appended "instance at xxx" tag.
310 procedure Set_Msg_Blank;
311 -- Sets a single blank in the message if the preceding character is a
312 -- non-blank character other than a left parenthesis. Has no effect if
313 -- manual quote mode is turned on.
315 procedure Set_Msg_Blank_Conditional;
316 -- Sets a single blank in the message if the preceding character is a
317 -- non-blank character other than a left parenthesis or quote. Has no
318 -- effect if manual quote mode is turned on.
320 procedure Set_Msg_Char (C : Character);
321 -- Add a single character to the current message. This routine does not
322 -- check for special insertion characters (they are just treated as text
323 -- characters if they occur).
325 procedure Set_Msg_Insertion_Column;
326 -- Handle column number insertion (@ insertion character)
328 procedure Set_Msg_Insertion_Name;
329 -- Handle name insertion (% insertion character)
331 procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr);
332 -- Handle line number insertion (# insertion character). Loc is the
333 -- location to be referenced, and Flag is the location at which the
334 -- flag is posted (used to determine whether to add "in file xxx")
336 procedure Set_Msg_Insertion_Node;
337 -- Handle node (name from node) insertion (& insertion character)
339 procedure Set_Msg_Insertion_Reserved_Name;
340 -- Handle insertion of reserved word name (* insertion character).
342 procedure Set_Msg_Insertion_Reserved_Word
343 (Text : String;
344 J : in out Integer);
345 -- Handle reserved word insertion (upper case letters). The Text argument
346 -- is the current error message input text, and J is an index which on
347 -- entry points to the first character of the reserved word, and on exit
348 -- points past the last character of the reserved word.
350 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr);
351 -- Handle type reference (right brace insertion character). Flag is the
352 -- location of the flag, which is provided for the internal call to
353 -- Set_Msg_Insertion_Line_Number,
355 procedure Set_Msg_Insertion_Uint;
356 -- Handle Uint insertion (^ insertion character)
358 procedure Set_Msg_Insertion_Unit_Name;
359 -- Handle unit name insertion ($ insertion character)
361 procedure Set_Msg_Insertion_File_Name;
362 -- Handle file name insertion (left brace insertion character)
364 procedure Set_Msg_Int (Line : Int);
365 -- Set the decimal representation of the argument in the error message
366 -- buffer with no leading zeroes output.
368 procedure Set_Msg_Name_Buffer;
369 -- Output name from Name_Buffer, with surrounding quotes unless manual
370 -- quotation mode is in effect.
372 procedure Set_Msg_Node (Node : Node_Id);
373 -- Add the sequence of characters for the name associated with the
374 -- given node to the current message.
376 procedure Set_Msg_Quote;
377 -- Set quote if in normal quote mode, nothing if in manual quote mode
379 procedure Set_Msg_Str (Text : String);
380 -- Add a sequence of characters to the current message. This routine does
381 -- not check for special insertion characters (they are just treated as
382 -- text characters if they occur).
384 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr);
385 -- Add a sequence of characters to the current message. The characters may
386 -- be one of the special insertion characters (see documentation in spec).
387 -- Flag is the location at which the error is to be posted, which is used
388 -- to determine whether or not the # insertion needs a file name. The
389 -- variables Msg_Buffer, Msglen, Is_Warning_Msg, and Is_Unconditional_Msg
390 -- are set on return.
392 procedure Set_Posted (N : Node_Id);
393 -- Sets the Error_Posted flag on the given node, and all its parents
394 -- that are subexpressions and then on the parent non-subexpression
395 -- construct that contains the original expression (this reduces the
396 -- number of cascaded messages)
398 procedure Set_Qualification (N : Nat; E : Entity_Id);
399 -- Outputs up to N levels of qualification for the given entity. For
400 -- example, the entity A.B.C.D will output B.C. if N = 2.
402 procedure Test_Warning_Msg (Msg : String);
403 -- Sets Is_Warning_Msg true if Msg is a warning message (contains a
404 -- question mark character), and False otherwise.
406 procedure Unwind_Internal_Type (Ent : in out Entity_Id);
407 -- This procedure is given an entity id for an internal type, i.e.
408 -- a type with an internal name. It unwinds the type to try to get
409 -- to something reasonably printable, generating prefixes like
410 -- "subtype of", "access to", etc along the way in the buffer. The
411 -- value in Ent on return is the final name to be printed. Hopefully
412 -- this is not an internal name, but in some internal name cases, it
413 -- is an internal name, and has to be printed anyway (although in this
414 -- case the message has been killed if possible). The global variable
415 -- Class_Flag is set to True if the resulting entity should have
416 -- 'Class appended to its name (see Add_Class procedure), and is
417 -- otherwise unchanged.
419 function Warnings_Suppressed (Loc : Source_Ptr) return Boolean;
420 -- Determines if given location is covered by a warnings off suppression
421 -- range in the warnings table (or is suppressed by compilation option,
422 -- which generates a warning range for the whole source file).
424 ---------------
425 -- Add_Class --
426 ---------------
428 procedure Add_Class is
429 begin
430 if Class_Flag then
431 Class_Flag := False;
432 Set_Msg_Char (''');
433 Get_Name_String (Name_Class);
434 Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
435 Set_Msg_Name_Buffer;
436 end if;
437 end Add_Class;
439 ----------------------
440 -- Buffer_Ends_With --
441 ----------------------
443 function Buffer_Ends_With (S : String) return Boolean is
444 Len : constant Natural := S'Length;
446 begin
447 return
448 Msglen > Len
449 and then Msg_Buffer (Msglen - Len) = ' '
450 and then Msg_Buffer (Msglen - Len + 1 .. Msglen) = S;
451 end Buffer_Ends_With;
453 -------------------
454 -- Buffer_Remove --
455 -------------------
457 procedure Buffer_Remove (S : String) is
458 begin
459 if Buffer_Ends_With (S) then
460 Msglen := Msglen - S'Length;
461 end if;
462 end Buffer_Remove;
464 -----------------------
465 -- Change_Error_Text --
466 -----------------------
468 procedure Change_Error_Text (Error_Id : Error_Msg_Id; New_Msg : String) is
469 Save_Next : Error_Msg_Id;
470 Err_Id : Error_Msg_Id := Error_Id;
472 begin
473 Set_Msg_Text (New_Msg, Errors.Table (Error_Id).Sptr);
474 Errors.Table (Error_Id).Text := new String'(Msg_Buffer (1 .. Msglen));
476 -- If in immediate error message mode, output modified error message now
477 -- This is just a bit tricky, because we want to output just a single
478 -- message, and the messages we modified is already linked in. We solve
479 -- this by temporarily resetting its forward pointer to empty.
481 if Debug_Flag_OO then
482 Save_Next := Errors.Table (Error_Id).Next;
483 Errors.Table (Error_Id).Next := No_Error_Msg;
484 Write_Eol;
485 Output_Source_Line
486 (Errors.Table (Error_Id).Line, Errors.Table (Error_Id).Sfile, True);
487 Output_Error_Msgs (Err_Id);
488 Errors.Table (Error_Id).Next := Save_Next;
489 end if;
490 end Change_Error_Text;
492 -----------------------------
493 -- Check_Duplicate_Message --
494 -----------------------------
496 procedure Check_Duplicate_Message (M1, M2 : Error_Msg_Id) is
497 L1, L2 : Error_Msg_Id;
498 N1, N2 : Error_Msg_Id;
500 procedure Delete_Msg (Delete, Keep : Error_Msg_Id);
501 -- Called to delete message Delete, keeping message Keep. Marks
502 -- all messages of Delete with deleted flag set to True, and also
503 -- makes sure that for the error messages that are retained the
504 -- preferred message is the one retained (we prefer the shorter
505 -- one in the case where one has an Instance tag). Note that we
506 -- always know that Keep has at least as many continuations as
507 -- Delete (since we always delete the shorter sequence).
509 procedure Delete_Msg (Delete, Keep : Error_Msg_Id) is
510 D, K : Error_Msg_Id;
512 begin
513 D := Delete;
514 K := Keep;
516 loop
517 Errors.Table (D).Deleted := True;
519 -- Adjust error message count
521 if Errors.Table (D).Warn then
522 Warnings_Detected := Warnings_Detected - 1;
523 else
524 Errors_Detected := Errors_Detected - 1;
525 end if;
527 -- Substitute shorter of the two error messages
529 if Errors.Table (K).Text'Length > Errors.Table (D).Text'Length then
530 Errors.Table (K).Text := Errors.Table (D).Text;
531 end if;
533 D := Errors.Table (D).Next;
534 K := Errors.Table (K).Next;
536 if D = No_Error_Msg or else not Errors.Table (D).Msg_Cont then
537 return;
538 end if;
539 end loop;
540 end Delete_Msg;
542 -- Start of processing for Check_Duplicate_Message
544 begin
545 -- Both messages must be non-continuation messages and not deleted
547 if Errors.Table (M1).Msg_Cont
548 or else Errors.Table (M2).Msg_Cont
549 or else Errors.Table (M1).Deleted
550 or else Errors.Table (M2).Deleted
551 then
552 return;
553 end if;
555 -- Definitely not equal if message text does not match
557 if not Same_Error (M1, M2) then
558 return;
559 end if;
561 -- Same text. See if all continuations are also identical
563 L1 := M1;
564 L2 := M2;
566 loop
567 N1 := Errors.Table (L1).Next;
568 N2 := Errors.Table (L2).Next;
570 -- If M1 continuations have run out, we delete M1, either the
571 -- messages have the same number of continuations, or M2 has
572 -- more and we prefer the one with more anyway.
574 if N1 = No_Error_Msg or else not Errors.Table (N1).Msg_Cont then
575 Delete_Msg (M1, M2);
576 return;
578 -- If M2 continuatins have run out, we delete M2
580 elsif N2 = No_Error_Msg or else not Errors.Table (N2).Msg_Cont then
581 Delete_Msg (M2, M1);
582 return;
584 -- Otherwise see if continuations are the same, if not, keep both
585 -- sequences, a curious case, but better to keep everything!
587 elsif not Same_Error (N1, N2) then
588 return;
590 -- If continuations are the same, continue scan
592 else
593 L1 := N1;
594 L2 := N2;
595 end if;
596 end loop;
597 end Check_Duplicate_Message;
599 ------------------------
600 -- Compilation_Errors --
601 ------------------------
603 function Compilation_Errors return Boolean is
604 begin
605 return Errors_Detected /= 0
606 or else (Warnings_Detected /= 0
607 and then Warning_Mode = Treat_As_Error);
608 end Compilation_Errors;
610 ------------------
611 -- Debug_Output --
612 ------------------
614 procedure Debug_Output (N : Node_Id) is
615 begin
616 if Debug_Flag_1 then
617 Write_Str ("*** following error message posted on node id = #");
618 Write_Int (Int (N));
619 Write_Str (" ***");
620 Write_Eol;
621 end if;
622 end Debug_Output;
624 ----------
625 -- dmsg --
626 ----------
628 procedure dmsg (Id : Error_Msg_Id) is
629 E : Error_Msg_Object renames Errors.Table (Id);
631 begin
632 w ("Dumping error message, Id = ", Int (Id));
633 w (" Text = ", E.Text.all);
634 w (" Next = ", Int (E.Next));
635 w (" Sfile = ", Int (E.Sfile));
637 Write_Str
638 (" Sptr = ");
639 Write_Location (E.Sptr);
640 Write_Eol;
642 Write_Str
643 (" Fptr = ");
644 Write_Location (E.Fptr);
645 Write_Eol;
647 w (" Line = ", Int (E.Line));
648 w (" Col = ", Int (E.Col));
649 w (" Warn = ", E.Warn);
650 w (" Uncond = ", E.Uncond);
651 w (" Msg_Cont = ", E.Msg_Cont);
652 w (" Deleted = ", E.Deleted);
654 Write_Eol;
655 end dmsg;
657 ---------------
658 -- Error_Msg --
659 ---------------
661 -- Error_Msg posts a flag at the given location, except that if the
662 -- Flag_Location points within a generic template and corresponds
663 -- to an instantiation of this generic template, then the actual
664 -- message will be posted on the generic instantiation, along with
665 -- additional messages referencing the generic declaration.
667 procedure Error_Msg (Msg : String; Flag_Location : Source_Ptr) is
668 Sindex : Source_File_Index;
669 -- Source index for flag location
671 Orig_Loc : Source_Ptr;
672 -- Original location of Flag_Location (i.e. location in original
673 -- template in instantiation case, otherwise unchanged).
675 begin
676 -- If we already have messages, and we are trying to place a message
677 -- at No_Location or in package Standard, then just ignore the attempt
678 -- since we assume that what is happening is some cascaded junk. Note
679 -- that this is safe in the sense that proceeding will surely bomb.
681 if Flag_Location < First_Source_Ptr
682 and then Errors_Detected > 0
683 then
684 return;
685 end if;
687 Sindex := Get_Source_File_Index (Flag_Location);
688 Test_Warning_Msg (Msg);
690 -- It is a fatal error to issue an error message when scanning from
691 -- the internal source buffer (see Sinput for further documentation)
693 pragma Assert (Source /= Internal_Source_Ptr);
695 -- Ignore warning message that is suppressed
697 Orig_Loc := Original_Location (Flag_Location);
699 if Is_Warning_Msg and then Warnings_Suppressed (Orig_Loc) then
700 return;
701 end if;
703 -- The idea at this stage is that we have two kinds of messages.
705 -- First, we have those that are to be placed as requested at
706 -- Flag_Location. This includes messages that have nothing to
707 -- do with generics, and also messages placed on generic templates
708 -- that reflect an error in the template itself. For such messages
709 -- we simply call Error_Msg_Internal to place the message in the
710 -- requested location.
712 if Instantiation (Sindex) = No_Location then
713 Error_Msg_Internal (Msg, Flag_Location, False);
714 return;
715 end if;
717 -- If we are trying to flag an error in an instantiation, we may have
718 -- a generic contract violation. What we generate in this case is:
720 -- instantiation error at ...
721 -- original error message
723 -- or
725 -- warning: in instantiation at
726 -- warning: original warning message
728 -- All these messages are posted at the location of the top level
729 -- instantiation. If there are nested instantiations, then the
730 -- instantiation error message can be repeated, pointing to each
731 -- of the relevant instantiations.
733 -- However, before we do this, we need to worry about the case where
734 -- indeed we are in an instantiation, but the message is a warning
735 -- message. In this case, it almost certainly a warning for the
736 -- template itself and so it is posted on the template. At least
737 -- this is the default mode, it can be cancelled (resulting the
738 -- warning being placed on the instance as in the error case) by
739 -- setting the global Warn_On_Instance True.
741 if (not Warn_On_Instance) and then Is_Warning_Msg then
742 Error_Msg_Internal (Msg, Flag_Location, False);
743 return;
744 end if;
746 -- Second, we need to worry about the case where there was a real error
747 -- in the template, and we are getting a repeat of this error in the
748 -- instantiation. We don't want to complain about the instantiation
749 -- in this case, since we have already flagged the template.
751 -- To deal with this case, just see if we have posted a message at
752 -- the template location already. If so, assume that the current
753 -- message is redundant. There could be cases in which this is not
754 -- a correct assumption, but it is not terrible to lose a message
755 -- about an incorrect instantiation given that we have already
756 -- flagged a message on the template.
758 for Err in Errors.First .. Errors.Last loop
759 if Errors.Table (Err).Sptr = Orig_Loc then
761 -- If the current message is a real error, as opposed to a
762 -- warning, then we don't want to let a warning on the
763 -- template inhibit a real error on the instantiation.
765 if Is_Warning_Msg
766 or else not Errors.Table (Err).Warn
767 then
768 return;
769 end if;
770 end if;
771 end loop;
773 -- OK, this is the case where we have an instantiation error, and
774 -- we need to generate the error on the instantiation, rather than
775 -- on the template. First, see if we have posted this exact error
776 -- before, and if so suppress it. It is not so easy to use the main
777 -- list of errors for this, since they have already been split up
778 -- according to the processing below. Consequently we use an auxiliary
779 -- data structure that just records these types of messages (it will
780 -- never have very many entries).
782 declare
783 Actual_Error_Loc : Source_Ptr;
784 -- Location of outer level instantiation in instantiation case, or
785 -- just a copy of Flag_Location in the normal case. This is the
786 -- location where all error messages will actually be posted.
788 Save_Error_Msg_Sloc : constant Source_Ptr := Error_Msg_Sloc;
789 -- Save possible location set for caller's message. We need to
790 -- use Error_Msg_Sloc for the location of the instantiation error
791 -- but we have to preserve a possible original value.
793 X : Source_File_Index;
795 Msg_Cont_Status : Boolean;
796 -- Used to label continuation lines in instantiation case with
797 -- proper Msg_Cont status.
799 begin
800 -- Loop to find highest level instantiation, where all error
801 -- messages will be placed.
803 X := Sindex;
804 loop
805 Actual_Error_Loc := Instantiation (X);
806 X := Get_Source_File_Index (Actual_Error_Loc);
807 exit when Instantiation (X) = No_Location;
808 end loop;
810 -- Since we are generating the messages at the instantiation
811 -- point in any case, we do not want the references to the
812 -- bad lines in the instance to be annotated with the location
813 -- of the instantiation.
815 Suppress_Instance_Location := True;
816 Msg_Cont_Status := False;
818 -- Loop to generate instantiation messages
820 Error_Msg_Sloc := Flag_Location;
821 X := Get_Source_File_Index (Flag_Location);
823 while Instantiation (X) /= No_Location loop
825 -- Suppress instantiation message on continuation lines
827 if Msg (1) /= '\' then
828 if Is_Warning_Msg then
829 Error_Msg_Internal
830 ("?in instantiation #",
831 Actual_Error_Loc, Msg_Cont_Status);
833 else
834 Error_Msg_Internal
835 ("instantiation error #",
836 Actual_Error_Loc, Msg_Cont_Status);
837 end if;
838 end if;
840 Error_Msg_Sloc := Instantiation (X);
841 X := Get_Source_File_Index (Error_Msg_Sloc);
842 Msg_Cont_Status := True;
843 end loop;
845 Suppress_Instance_Location := False;
846 Error_Msg_Sloc := Save_Error_Msg_Sloc;
848 -- Here we output the original message on the outer instantiation
850 Error_Msg_Internal (Msg, Actual_Error_Loc, Msg_Cont_Status);
851 end;
852 end Error_Msg;
854 ------------------
855 -- Error_Msg_AP --
856 ------------------
858 procedure Error_Msg_AP (Msg : String) is
859 S1 : Source_Ptr;
860 C : Character;
862 begin
863 -- If we had saved the Scan_Ptr value after scanning the previous
864 -- token, then we would have exactly the right place for putting
865 -- the flag immediately at hand. However, that would add at least
866 -- two instructions to a Scan call *just* to service the possibility
867 -- of an Error_Msg_AP call. So instead we reconstruct that value.
869 -- We have two possibilities, start with Prev_Token_Ptr and skip over
870 -- the current token, which is made harder by the possibility that this
871 -- token may be in error, or start with Token_Ptr and work backwards.
872 -- We used to take the second approach, but it's hard because of
873 -- comments, and harder still because things that look like comments
874 -- can appear inside strings. So now we take the first approach.
876 -- Note: in the case where there is no previous token, Prev_Token_Ptr
877 -- is set to Source_First, which is a reasonable position for the
878 -- error flag in this situation.
880 S1 := Prev_Token_Ptr;
881 C := Source (S1);
883 -- If the previous token is a string literal, we need a special approach
884 -- since there may be white space inside the literal and we don't want
885 -- to stop on that white space.
887 if Prev_Token = Tok_String_Literal then
888 loop
889 S1 := S1 + 1;
891 if Source (S1) = C then
892 S1 := S1 + 1;
893 exit when Source (S1) /= C;
894 elsif Source (S1) in Line_Terminator then
895 exit;
896 end if;
897 end loop;
899 -- Character literal also needs special handling
901 elsif Prev_Token = Tok_Char_Literal then
902 S1 := S1 + 3;
904 -- Otherwise we search forward for the end of the current token, marked
905 -- by a line terminator, white space, a comment symbol or if we bump
906 -- into the following token (i.e. the current token)
908 else
909 while Source (S1) not in Line_Terminator
910 and then Source (S1) /= ' '
911 and then Source (S1) /= ASCII.HT
912 and then (Source (S1) /= '-' or else Source (S1 + 1) /= '-')
913 and then S1 /= Token_Ptr
914 loop
915 S1 := S1 + 1;
916 end loop;
917 end if;
919 -- S1 is now set to the location for the flag
921 Error_Msg (Msg, S1);
923 end Error_Msg_AP;
925 ------------------
926 -- Error_Msg_BC --
927 ------------------
929 procedure Error_Msg_BC (Msg : String) is
930 begin
931 -- If we are at end of file, post the flag after the previous token
933 if Token = Tok_EOF then
934 Error_Msg_AP (Msg);
936 -- If we are at start of file, post the flag at the current token
938 elsif Token_Ptr = Source_First (Current_Source_File) then
939 Error_Msg_SC (Msg);
941 -- If the character before the current token is a space or a horizontal
942 -- tab, then we place the flag on this character (in the case of a tab
943 -- we would really like to place it in the "last" character of the tab
944 -- space, but that it too much trouble to worry about).
946 elsif Source (Token_Ptr - 1) = ' '
947 or else Source (Token_Ptr - 1) = ASCII.HT
948 then
949 Error_Msg (Msg, Token_Ptr - 1);
951 -- If there is no space or tab before the current token, then there is
952 -- no room to place the flag before the token, so we place it on the
953 -- token instead (this happens for example at the start of a line).
955 else
956 Error_Msg (Msg, Token_Ptr);
957 end if;
958 end Error_Msg_BC;
960 ------------------------
961 -- Error_Msg_Internal --
962 ------------------------
964 procedure Error_Msg_Internal
965 (Msg : String;
966 Flag_Location : Source_Ptr;
967 Msg_Cont : Boolean)
969 Next_Msg : Error_Msg_Id;
970 -- Pointer to next message at insertion point
972 Prev_Msg : Error_Msg_Id;
973 -- Pointer to previous message at insertion point
975 Temp_Msg : Error_Msg_Id;
977 Orig_Loc : constant Source_Ptr := Original_Location (Flag_Location);
979 procedure Handle_Fatal_Error;
980 -- Internal procedure to do all error message handling other than
981 -- bumping the error count and arranging for the message to be output.
983 procedure Handle_Fatal_Error is
984 begin
985 -- Turn off code generation if not done already
987 if Operating_Mode = Generate_Code then
988 Operating_Mode := Check_Semantics;
989 Expander_Active := False;
990 end if;
992 -- Set the fatal error flag in the unit table unless we are
993 -- in Try_Semantics mode. This stops the semantics from being
994 -- performed if we find a parser error. This is skipped if we
995 -- are currently dealing with the configuration pragma file.
997 if not Try_Semantics
998 and then Current_Source_Unit /= No_Unit
999 then
1000 Set_Fatal_Error (Get_Source_Unit (Orig_Loc));
1001 end if;
1002 end Handle_Fatal_Error;
1004 -- Start of processing for Error_Msg_Internal
1006 begin
1007 if Raise_Exception_On_Error /= 0 then
1008 raise Error_Msg_Exception;
1009 end if;
1011 Continuation := Msg_Cont;
1012 Suppress_Message := False;
1013 Kill_Message := False;
1014 Set_Msg_Text (Msg, Orig_Loc);
1016 -- Kill continuation if parent message killed
1018 if Continuation and Last_Killed then
1019 return;
1020 end if;
1022 -- Return without doing anything if message is suppressed
1024 if Suppress_Message
1025 and not All_Errors_Mode
1026 and not (Msg (Msg'Last) = '!')
1027 then
1028 if not Continuation then
1029 Last_Killed := True;
1030 end if;
1032 return;
1033 end if;
1035 -- Return without doing anything if message is killed and this
1036 -- is not the first error message. The philosophy is that if we
1037 -- get a weird error message and we already have had a message,
1038 -- then we hope the weird message is a junk cascaded message
1040 if Kill_Message
1041 and then not All_Errors_Mode
1042 and then Errors_Detected /= 0
1043 then
1044 if not Continuation then
1045 Last_Killed := True;
1046 end if;
1048 return;
1049 end if;
1051 -- Immediate return if warning message and warnings are suppressed
1053 if Is_Warning_Msg and then Warnings_Suppressed (Orig_Loc) then
1054 Cur_Msg := No_Error_Msg;
1055 return;
1056 end if;
1058 -- If message is to be ignored in special ignore message mode, this is
1059 -- where we do this special processing, bypassing message output.
1061 if Ignore_Errors_Enable > 0 then
1062 Handle_Fatal_Error;
1063 return;
1064 end if;
1066 -- Otherwise build error message object for new message
1068 Errors.Increment_Last;
1069 Cur_Msg := Errors.Last;
1070 Errors.Table (Cur_Msg).Text := new String'(Msg_Buffer (1 .. Msglen));
1071 Errors.Table (Cur_Msg).Next := No_Error_Msg;
1072 Errors.Table (Cur_Msg).Sptr := Orig_Loc;
1073 Errors.Table (Cur_Msg).Fptr := Flag_Location;
1074 Errors.Table (Cur_Msg).Sfile := Get_Source_File_Index (Orig_Loc);
1075 Errors.Table (Cur_Msg).Line := Get_Physical_Line_Number (Orig_Loc);
1076 Errors.Table (Cur_Msg).Col := Get_Column_Number (Orig_Loc);
1077 Errors.Table (Cur_Msg).Warn := Is_Warning_Msg;
1078 Errors.Table (Cur_Msg).Uncond := Is_Unconditional_Msg;
1079 Errors.Table (Cur_Msg).Msg_Cont := Continuation;
1080 Errors.Table (Cur_Msg).Deleted := False;
1082 -- If immediate errors mode set, output error message now. Also output
1083 -- now if the -d1 debug flag is set (so node number message comes out
1084 -- just before actual error message)
1086 if Debug_Flag_OO or else Debug_Flag_1 then
1087 Write_Eol;
1088 Output_Source_Line (Errors.Table (Cur_Msg).Line,
1089 Errors.Table (Cur_Msg).Sfile, True);
1090 Temp_Msg := Cur_Msg;
1091 Output_Error_Msgs (Temp_Msg);
1093 -- If not in immediate errors mode, then we insert the message in the
1094 -- error chain for later output by Finalize. The messages are sorted
1095 -- first by unit (main unit comes first), and within a unit by source
1096 -- location (earlier flag location first in the chain).
1098 else
1099 Prev_Msg := No_Error_Msg;
1100 Next_Msg := Error_Msgs;
1102 while Next_Msg /= No_Error_Msg loop
1103 exit when
1104 Errors.Table (Cur_Msg).Sfile < Errors.Table (Next_Msg).Sfile;
1106 if Errors.Table (Cur_Msg).Sfile =
1107 Errors.Table (Next_Msg).Sfile
1108 then
1109 exit when Orig_Loc < Errors.Table (Next_Msg).Sptr;
1110 end if;
1112 Prev_Msg := Next_Msg;
1113 Next_Msg := Errors.Table (Next_Msg).Next;
1114 end loop;
1116 -- Now we insert the new message in the error chain. The insertion
1117 -- point for the message is after Prev_Msg and before Next_Msg.
1119 -- The possible insertion point for the new message is after Prev_Msg
1120 -- and before Next_Msg. However, this is where we do a special check
1121 -- for redundant parsing messages, defined as messages posted on the
1122 -- same line. The idea here is that probably such messages are junk
1123 -- from the parser recovering. In full errors mode, we don't do this
1124 -- deletion, but otherwise such messages are discarded at this stage.
1126 if Prev_Msg /= No_Error_Msg
1127 and then Errors.Table (Prev_Msg).Line =
1128 Errors.Table (Cur_Msg).Line
1129 and then Errors.Table (Prev_Msg).Sfile =
1130 Errors.Table (Cur_Msg).Sfile
1131 and then Compiler_State = Parsing
1132 and then not All_Errors_Mode
1133 then
1134 -- Don't delete unconditional messages and at this stage,
1135 -- don't delete continuation lines (we attempted to delete
1136 -- those earlier if the parent message was deleted.
1138 if not Errors.Table (Cur_Msg).Uncond
1139 and then not Continuation
1140 then
1142 -- Don't delete if prev msg is warning and new msg is
1143 -- an error. This is because we don't want a real error
1144 -- masked by a warning. In all other cases (that is parse
1145 -- errors for the same line that are not unconditional)
1146 -- we do delete the message. This helps to avoid
1147 -- junk extra messages from cascaded parsing errors
1149 if not Errors.Table (Prev_Msg).Warn
1150 or else Errors.Table (Cur_Msg).Warn
1151 then
1152 -- All tests passed, delete the message by simply
1153 -- returning without any further processing.
1155 if not Continuation then
1156 Last_Killed := True;
1157 end if;
1159 return;
1160 end if;
1161 end if;
1162 end if;
1164 -- Come here if message is to be inserted in the error chain
1166 if not Continuation then
1167 Last_Killed := False;
1168 end if;
1170 if Prev_Msg = No_Error_Msg then
1171 Error_Msgs := Cur_Msg;
1172 else
1173 Errors.Table (Prev_Msg).Next := Cur_Msg;
1174 end if;
1176 Errors.Table (Cur_Msg).Next := Next_Msg;
1177 end if;
1179 -- Bump appropriate statistics count
1181 if Errors.Table (Cur_Msg).Warn then
1182 Warnings_Detected := Warnings_Detected + 1;
1183 else
1184 Errors_Detected := Errors_Detected + 1;
1185 Handle_Fatal_Error;
1186 end if;
1188 -- Terminate if max errors reached
1190 if Errors_Detected + Warnings_Detected = Maximum_Errors then
1191 raise Unrecoverable_Error;
1192 end if;
1194 end Error_Msg_Internal;
1196 -----------------
1197 -- Error_Msg_N --
1198 -----------------
1200 procedure Error_Msg_N (Msg : String; N : Node_Or_Entity_Id) is
1201 begin
1202 if No_Warnings (N) then
1203 Test_Warning_Msg (Msg);
1205 if Is_Warning_Msg then
1206 return;
1207 end if;
1208 end if;
1210 if All_Errors_Mode
1211 or else Msg (Msg'Last) = '!'
1212 or else OK_Node (N)
1213 or else (Msg (1) = '\' and not Last_Killed)
1214 then
1215 Debug_Output (N);
1216 Error_Msg_Node_1 := N;
1217 Error_Msg (Msg, Sloc (N));
1219 else
1220 Last_Killed := True;
1221 end if;
1223 if not Is_Warning_Msg then
1224 Set_Posted (N);
1225 end if;
1226 end Error_Msg_N;
1228 ------------------
1229 -- Error_Msg_NE --
1230 ------------------
1232 procedure Error_Msg_NE
1233 (Msg : String;
1234 N : Node_Or_Entity_Id;
1235 E : Node_Or_Entity_Id)
1237 begin
1238 if No_Warnings (N) or else No_Warnings (E) then
1239 Test_Warning_Msg (Msg);
1241 if Is_Warning_Msg then
1242 return;
1243 end if;
1244 end if;
1246 if All_Errors_Mode
1247 or else Msg (Msg'Last) = '!'
1248 or else OK_Node (N)
1249 or else (Msg (1) = '\' and not Last_Killed)
1250 then
1251 Debug_Output (N);
1252 Error_Msg_Node_1 := E;
1253 Error_Msg (Msg, Sloc (N));
1255 else
1256 Last_Killed := True;
1257 end if;
1259 if not Is_Warning_Msg then
1260 Set_Posted (N);
1261 end if;
1262 end Error_Msg_NE;
1264 -----------------
1265 -- Error_Msg_S --
1266 -----------------
1268 procedure Error_Msg_S (Msg : String) is
1269 begin
1270 Error_Msg (Msg, Scan_Ptr);
1271 end Error_Msg_S;
1273 ------------------
1274 -- Error_Msg_SC --
1275 ------------------
1277 procedure Error_Msg_SC (Msg : String) is
1278 begin
1279 -- If we are at end of file, post the flag after the previous token
1281 if Token = Tok_EOF then
1282 Error_Msg_AP (Msg);
1284 -- For all other cases the message is posted at the current token
1285 -- pointer position
1287 else
1288 Error_Msg (Msg, Token_Ptr);
1289 end if;
1290 end Error_Msg_SC;
1292 ------------------
1293 -- Error_Msg_SP --
1294 ------------------
1296 procedure Error_Msg_SP (Msg : String) is
1297 begin
1298 -- Note: in the case where there is no previous token, Prev_Token_Ptr
1299 -- is set to Source_First, which is a reasonable position for the
1300 -- error flag in this situation
1302 Error_Msg (Msg, Prev_Token_Ptr);
1303 end Error_Msg_SP;
1305 --------------
1306 -- Finalize --
1307 --------------
1309 procedure Finalize is
1310 Cur : Error_Msg_Id;
1311 Nxt : Error_Msg_Id;
1312 E, F : Error_Msg_Id;
1313 Err_Flag : Boolean;
1315 begin
1316 -- Reset current error source file if the main unit has a pragma
1317 -- Source_Reference. This ensures outputting the proper name of
1318 -- the source file in this situation.
1320 if Num_SRef_Pragmas (Main_Source_File) /= 0 then
1321 Current_Error_Source_File := No_Source_File;
1322 end if;
1324 -- Eliminate any duplicated error messages from the list. This is
1325 -- done after the fact to avoid problems with Change_Error_Text.
1327 Cur := Error_Msgs;
1328 while Cur /= No_Error_Msg loop
1329 Nxt := Errors.Table (Cur).Next;
1331 F := Nxt;
1332 while F /= No_Error_Msg
1333 and then Errors.Table (F).Sptr = Errors.Table (Cur).Sptr
1334 loop
1335 Check_Duplicate_Message (Cur, F);
1336 F := Errors.Table (F).Next;
1337 end loop;
1339 Cur := Nxt;
1340 end loop;
1342 -- Brief Error mode
1344 if Brief_Output or (not Full_List and not Verbose_Mode) then
1345 E := Error_Msgs;
1346 Set_Standard_Error;
1348 while E /= No_Error_Msg loop
1349 if not Errors.Table (E).Deleted and then not Debug_Flag_KK then
1350 Write_Name (Reference_Name (Errors.Table (E).Sfile));
1351 Write_Char (':');
1352 Write_Int (Int (Physical_To_Logical
1353 (Errors.Table (E).Line,
1354 Errors.Table (E).Sfile)));
1355 Write_Char (':');
1357 if Errors.Table (E).Col < 10 then
1358 Write_Char ('0');
1359 end if;
1361 Write_Int (Int (Errors.Table (E).Col));
1362 Write_Str (": ");
1363 Output_Msg_Text (E);
1364 Write_Eol;
1365 end if;
1367 E := Errors.Table (E).Next;
1368 end loop;
1370 Set_Standard_Output;
1371 end if;
1373 -- Full source listing case
1375 if Full_List then
1376 List_Pragmas_Index := 1;
1377 List_Pragmas_Mode := True;
1378 E := Error_Msgs;
1379 Write_Eol;
1381 -- First list initial main source file with its error messages
1383 for N in 1 .. Last_Source_Line (Main_Source_File) loop
1384 Err_Flag :=
1385 E /= No_Error_Msg
1386 and then Errors.Table (E).Line = N
1387 and then Errors.Table (E).Sfile = Main_Source_File;
1389 Output_Source_Line (N, Main_Source_File, Err_Flag);
1391 if Err_Flag then
1392 Output_Error_Msgs (E);
1394 if not Debug_Flag_2 then
1395 Write_Eol;
1396 end if;
1397 end if;
1399 end loop;
1401 -- Then output errors, if any, for subsidiary units
1403 while E /= No_Error_Msg
1404 and then Errors.Table (E).Sfile /= Main_Source_File
1405 loop
1406 Write_Eol;
1407 Output_Source_Line
1408 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
1409 Output_Error_Msgs (E);
1410 end loop;
1411 end if;
1413 -- Verbose mode (error lines only with error flags)
1415 if Verbose_Mode and not Full_List then
1416 E := Error_Msgs;
1418 -- Loop through error lines
1420 while E /= No_Error_Msg loop
1421 Write_Eol;
1422 Output_Source_Line
1423 (Errors.Table (E).Line, Errors.Table (E).Sfile, True);
1424 Output_Error_Msgs (E);
1425 end loop;
1426 end if;
1428 -- Output error summary if verbose or full list mode
1430 if Verbose_Mode or else Full_List then
1432 -- Extra blank line if error messages or source listing were output
1434 if Errors_Detected + Warnings_Detected > 0 or else Full_List then
1435 Write_Eol;
1436 end if;
1438 -- Message giving number of lines read and number of errors detected.
1439 -- This normally goes to Standard_Output. The exception is when brief
1440 -- mode is not set, verbose mode (or full list mode) is set, and
1441 -- there are errors. In this case we send the message to standard
1442 -- error to make sure that *something* appears on standard error in
1443 -- an error situation.
1445 -- Formerly, only the "# errors" suffix was sent to stderr, whereas
1446 -- "# lines:" appeared on stdout. This caused problems on VMS when
1447 -- the stdout buffer was flushed, giving an extra line feed after
1448 -- the prefix.
1450 if Errors_Detected + Warnings_Detected /= 0
1451 and then not Brief_Output
1452 and then (Verbose_Mode or Full_List)
1453 then
1454 Set_Standard_Error;
1455 end if;
1457 -- Message giving total number of lines
1459 Write_Str (" ");
1460 Write_Int (Num_Source_Lines (Main_Source_File));
1462 if Num_Source_Lines (Main_Source_File) = 1 then
1463 Write_Str (" line: ");
1464 else
1465 Write_Str (" lines: ");
1466 end if;
1468 if Errors_Detected = 0 then
1469 Write_Str ("No errors");
1471 elsif Errors_Detected = 1 then
1472 Write_Str ("1 error");
1474 else
1475 Write_Int (Errors_Detected);
1476 Write_Str (" errors");
1477 end if;
1479 if Warnings_Detected /= 0 then
1480 Write_Str (", ");
1481 Write_Int (Warnings_Detected);
1482 Write_Str (" warning");
1484 if Warnings_Detected /= 1 then
1485 Write_Char ('s');
1486 end if;
1488 if Warning_Mode = Treat_As_Error then
1489 Write_Str (" (treated as error");
1491 if Warnings_Detected /= 1 then
1492 Write_Char ('s');
1493 end if;
1495 Write_Char (')');
1496 end if;
1497 end if;
1499 Write_Eol;
1500 Set_Standard_Output;
1501 end if;
1503 if Maximum_Errors /= 0
1504 and then Errors_Detected + Warnings_Detected = Maximum_Errors
1505 then
1506 Set_Standard_Error;
1507 Write_Str ("fatal error: maximum errors reached");
1508 Write_Eol;
1509 Set_Standard_Output;
1510 end if;
1512 if Warning_Mode = Treat_As_Error then
1513 Errors_Detected := Errors_Detected + Warnings_Detected;
1514 Warnings_Detected := 0;
1515 end if;
1517 end Finalize;
1519 ------------------
1520 -- Get_Location --
1521 ------------------
1523 function Get_Location (E : Error_Msg_Id) return Source_Ptr is
1524 begin
1525 return Errors.Table (E).Sptr;
1526 end Get_Location;
1528 ----------------
1529 -- Get_Msg_Id --
1530 ----------------
1532 function Get_Msg_Id return Error_Msg_Id is
1533 begin
1534 return Cur_Msg;
1535 end Get_Msg_Id;
1537 ----------------
1538 -- Initialize --
1539 ----------------
1541 procedure Initialize is
1542 begin
1543 Errors.Init;
1544 Error_Msgs := No_Error_Msg;
1545 Errors_Detected := 0;
1546 Warnings_Detected := 0;
1547 Cur_Msg := No_Error_Msg;
1548 List_Pragmas.Init;
1550 -- Initialize warnings table, if all warnings are suppressed, supply
1551 -- an initial dummy entry covering all possible source locations.
1553 Warnings.Init;
1555 if Warning_Mode = Suppress then
1556 Warnings.Increment_Last;
1557 Warnings.Table (Warnings.Last).Start := Source_Ptr'First;
1558 Warnings.Table (Warnings.Last).Stop := Source_Ptr'Last;
1559 end if;
1561 end Initialize;
1563 -----------------
1564 -- No_Warnings --
1565 -----------------
1567 function No_Warnings (N : Node_Or_Entity_Id) return Boolean is
1568 begin
1569 if Error_Posted (N) then
1570 return True;
1572 elsif Nkind (N) in N_Entity and then Warnings_Off (N) then
1573 return True;
1575 elsif Is_Entity_Name (N)
1576 and then Present (Entity (N))
1577 and then Warnings_Off (Entity (N))
1578 then
1579 return True;
1581 else
1582 return False;
1583 end if;
1584 end No_Warnings;
1586 -------------
1587 -- OK_Node --
1588 -------------
1590 function OK_Node (N : Node_Id) return Boolean is
1591 K : constant Node_Kind := Nkind (N);
1593 begin
1594 if Error_Posted (N) then
1595 return False;
1597 elsif K in N_Has_Etype
1598 and then Present (Etype (N))
1599 and then Error_Posted (Etype (N))
1600 then
1601 return False;
1603 elsif (K in N_Op
1604 or else K = N_Attribute_Reference
1605 or else K = N_Character_Literal
1606 or else K = N_Expanded_Name
1607 or else K = N_Identifier
1608 or else K = N_Operator_Symbol)
1609 and then Present (Entity (N))
1610 and then Error_Posted (Entity (N))
1611 then
1612 return False;
1613 else
1614 return True;
1615 end if;
1616 end OK_Node;
1618 -----------------------
1619 -- Output_Error_Msgs --
1620 -----------------------
1622 procedure Output_Error_Msgs (E : in out Error_Msg_Id) is
1623 P : Source_Ptr;
1624 T : Error_Msg_Id;
1625 S : Error_Msg_Id;
1627 Flag_Num : Pos;
1628 Mult_Flags : Boolean := False;
1630 begin
1631 S := E;
1633 -- Skip deleted messages at start
1635 if Errors.Table (S).Deleted then
1636 Set_Next_Non_Deleted_Msg (S);
1637 end if;
1639 -- Figure out if we will place more than one error flag on this line
1641 T := S;
1642 while T /= No_Error_Msg
1643 and then Errors.Table (T).Line = Errors.Table (E).Line
1644 and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
1645 loop
1646 if Errors.Table (T).Sptr > Errors.Table (E).Sptr then
1647 Mult_Flags := True;
1648 end if;
1650 Set_Next_Non_Deleted_Msg (T);
1651 end loop;
1653 -- Output the error flags. The circuit here makes sure that the tab
1654 -- characters in the original line are properly accounted for. The
1655 -- eight blanks at the start are to match the line number.
1657 if not Debug_Flag_2 then
1658 Write_Str (" ");
1659 P := Line_Start (Errors.Table (E).Sptr);
1660 Flag_Num := 1;
1662 -- Loop through error messages for this line to place flags
1664 T := S;
1665 while T /= No_Error_Msg
1666 and then Errors.Table (T).Line = Errors.Table (E).Line
1667 and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
1668 loop
1669 -- Loop to output blanks till current flag position
1671 while P < Errors.Table (T).Sptr loop
1672 if Source_Text (Errors.Table (T).Sfile) (P) = ASCII.HT then
1673 Write_Char (ASCII.HT);
1674 else
1675 Write_Char (' ');
1676 end if;
1678 P := P + 1;
1679 end loop;
1681 -- Output flag (unless already output, this happens if more
1682 -- than one error message occurs at the same flag position).
1684 if P = Errors.Table (T).Sptr then
1685 if (Flag_Num = 1 and then not Mult_Flags)
1686 or else Flag_Num > 9
1687 then
1688 Write_Char ('|');
1689 else
1690 Write_Char (Character'Val (Character'Pos ('0') + Flag_Num));
1691 end if;
1693 P := P + 1;
1694 end if;
1696 Set_Next_Non_Deleted_Msg (T);
1697 Flag_Num := Flag_Num + 1;
1698 end loop;
1700 Write_Eol;
1701 end if;
1703 -- Now output the error messages
1705 T := S;
1706 while T /= No_Error_Msg
1707 and then Errors.Table (T).Line = Errors.Table (E).Line
1708 and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
1710 loop
1711 Write_Str (" >>> ");
1712 Output_Msg_Text (T);
1714 if Debug_Flag_2 then
1715 while Column < 74 loop
1716 Write_Char (' ');
1717 end loop;
1719 Write_Str (" <<<");
1720 end if;
1722 Write_Eol;
1723 Set_Next_Non_Deleted_Msg (T);
1724 end loop;
1726 E := T;
1727 end Output_Error_Msgs;
1729 ------------------------
1730 -- Output_Line_Number --
1731 ------------------------
1733 procedure Output_Line_Number (L : Logical_Line_Number) is
1734 D : Int; -- next digit
1735 C : Character; -- next character
1736 Z : Boolean; -- flag for zero suppress
1737 N, M : Int; -- temporaries
1739 begin
1740 if L = No_Line_Number then
1741 Write_Str (" ");
1743 else
1744 Z := False;
1745 N := Int (L);
1747 M := 100_000;
1748 while M /= 0 loop
1749 D := Int (N / M);
1750 N := N rem M;
1751 M := M / 10;
1753 if D = 0 then
1754 if Z then
1755 C := '0';
1756 else
1757 C := ' ';
1758 end if;
1759 else
1760 Z := True;
1761 C := Character'Val (D + 48);
1762 end if;
1764 Write_Char (C);
1765 end loop;
1767 Write_Str (". ");
1768 end if;
1769 end Output_Line_Number;
1771 ---------------------
1772 -- Output_Msg_Text --
1773 ---------------------
1775 procedure Output_Msg_Text (E : Error_Msg_Id) is
1776 begin
1777 if Errors.Table (E).Warn then
1778 if Errors.Table (E).Text'Length > 7
1779 and then Errors.Table (E).Text (1 .. 7) /= "(style)"
1780 then
1781 Write_Str ("warning: ");
1782 end if;
1784 elsif Opt.Unique_Error_Tag then
1785 Write_Str ("error: ");
1786 end if;
1788 Write_Str (Errors.Table (E).Text.all);
1789 end Output_Msg_Text;
1791 ------------------------
1792 -- Output_Source_Line --
1793 ------------------------
1795 procedure Output_Source_Line
1796 (L : Physical_Line_Number;
1797 Sfile : Source_File_Index;
1798 Errs : Boolean)
1800 S : Source_Ptr;
1801 C : Character;
1803 Line_Number_Output : Boolean := False;
1804 -- Set True once line number is output
1806 begin
1807 if Sfile /= Current_Error_Source_File then
1808 Write_Str ("==============Error messages for source file: ");
1809 Write_Name (Full_File_Name (Sfile));
1810 Write_Eol;
1812 if Num_SRef_Pragmas (Sfile) > 0 then
1813 Write_Str ("--------------Line numbers from file: ");
1814 Write_Name (Full_Ref_Name (Sfile));
1816 -- Write starting line, except do not write it if we had more
1817 -- than one source reference pragma, since in this case there
1818 -- is no very useful number to write.
1820 Write_Str (" (starting at line ");
1821 Write_Int (Int (First_Mapped_Line (Sfile)));
1822 Write_Char (')');
1823 Write_Eol;
1824 end if;
1826 Current_Error_Source_File := Sfile;
1827 end if;
1829 if Errs or List_Pragmas_Mode then
1830 Output_Line_Number (Physical_To_Logical (L, Sfile));
1831 Line_Number_Output := True;
1832 end if;
1834 S := Line_Start (L, Sfile);
1836 loop
1837 C := Source_Text (Sfile) (S);
1838 exit when C = ASCII.LF or else C = ASCII.CR or else C = EOF;
1840 -- Deal with matching entry in List_Pragmas table
1842 if Full_List
1843 and then List_Pragmas_Index <= List_Pragmas.Last
1844 and then S = List_Pragmas.Table (List_Pragmas_Index).Ploc
1845 then
1846 case List_Pragmas.Table (List_Pragmas_Index).Ptyp is
1847 when Page =>
1848 Write_Char (C);
1850 -- Ignore if on line with errors so that error flags
1851 -- get properly listed with the error line .
1853 if not Errs then
1854 Write_Char (ASCII.FF);
1855 end if;
1857 when List_On =>
1858 List_Pragmas_Mode := True;
1860 if not Line_Number_Output then
1861 Output_Line_Number (Physical_To_Logical (L, Sfile));
1862 Line_Number_Output := True;
1863 end if;
1865 Write_Char (C);
1867 when List_Off =>
1868 Write_Char (C);
1869 List_Pragmas_Mode := False;
1870 end case;
1872 List_Pragmas_Index := List_Pragmas_Index + 1;
1874 -- Normal case (no matching entry in List_Pragmas table)
1876 else
1877 if Errs or List_Pragmas_Mode then
1878 Write_Char (C);
1879 end if;
1880 end if;
1882 S := S + 1;
1883 end loop;
1885 if Line_Number_Output then
1886 Write_Eol;
1887 end if;
1888 end Output_Source_Line;
1890 --------------------
1891 -- Purge_Messages --
1892 --------------------
1894 procedure Purge_Messages (From : Source_Ptr; To : Source_Ptr) is
1895 E : Error_Msg_Id;
1897 function To_Be_Purged (E : Error_Msg_Id) return Boolean;
1898 -- Returns True for a message that is to be purged. Also adjusts
1899 -- error counts appropriately.
1901 function To_Be_Purged (E : Error_Msg_Id) return Boolean is
1902 begin
1903 if E /= No_Error_Msg
1904 and then Errors.Table (E).Sptr > From
1905 and then Errors.Table (E).Sptr < To
1906 then
1907 if Errors.Table (E).Warn then
1908 Warnings_Detected := Warnings_Detected - 1;
1909 else
1910 Errors_Detected := Errors_Detected - 1;
1911 end if;
1913 return True;
1915 else
1916 return False;
1917 end if;
1918 end To_Be_Purged;
1920 -- Start of processing for Purge_Messages
1922 begin
1923 while To_Be_Purged (Error_Msgs) loop
1924 Error_Msgs := Errors.Table (Error_Msgs).Next;
1925 end loop;
1927 E := Error_Msgs;
1928 while E /= No_Error_Msg loop
1929 while To_Be_Purged (Errors.Table (E).Next) loop
1930 Errors.Table (E).Next :=
1931 Errors.Table (Errors.Table (E).Next).Next;
1932 end loop;
1934 E := Errors.Table (E).Next;
1935 end loop;
1936 end Purge_Messages;
1938 -----------------------------
1939 -- Remove_Warning_Messages --
1940 -----------------------------
1942 procedure Remove_Warning_Messages (N : Node_Id) is
1944 function Check_For_Warning (N : Node_Id) return Traverse_Result;
1945 -- This function checks one node for a possible warning message.
1947 function Check_All_Warnings is new
1948 Traverse_Func (Check_For_Warning);
1949 -- This defines the traversal operation
1951 -----------------------
1952 -- Check_For_Warning --
1953 -----------------------
1955 function Check_For_Warning (N : Node_Id) return Traverse_Result is
1956 Loc : constant Source_Ptr := Sloc (N);
1957 E : Error_Msg_Id;
1959 function To_Be_Removed (E : Error_Msg_Id) return Boolean;
1960 -- Returns True for a message that is to be removed. Also adjusts
1961 -- warning count appropriately.
1963 -------------------
1964 -- To_Be_Removed --
1965 -------------------
1967 function To_Be_Removed (E : Error_Msg_Id) return Boolean is
1968 begin
1969 if E /= No_Error_Msg
1970 and then Errors.Table (E).Fptr = Loc
1971 and then Errors.Table (E).Warn
1972 then
1973 Warnings_Detected := Warnings_Detected - 1;
1974 return True;
1975 else
1976 return False;
1977 end if;
1978 end To_Be_Removed;
1980 -- Start of processing for Check_For_Warnings
1982 begin
1983 while To_Be_Removed (Error_Msgs) loop
1984 Error_Msgs := Errors.Table (Error_Msgs).Next;
1985 end loop;
1987 E := Error_Msgs;
1988 while E /= No_Error_Msg loop
1989 while To_Be_Removed (Errors.Table (E).Next) loop
1990 Errors.Table (E).Next :=
1991 Errors.Table (Errors.Table (E).Next).Next;
1992 end loop;
1994 E := Errors.Table (E).Next;
1995 end loop;
1997 if Nkind (N) = N_Raise_Constraint_Error
1998 and then Original_Node (N) /= N
1999 then
2000 -- Warnings may have been posted on subexpressions of
2001 -- the original tree. We temporarily replace the raise
2002 -- statement with the original expression to remove
2003 -- those warnings, whose sloc do not match those of
2004 -- any node in the current tree.
2006 declare
2007 Old : Node_Id := N;
2008 Status : Traverse_Result;
2010 begin
2011 Rewrite (N, Original_Node (N));
2012 Status := Check_For_Warning (N);
2013 Rewrite (N, Old);
2014 return Status;
2015 end;
2017 else
2018 return OK;
2019 end if;
2020 end Check_For_Warning;
2022 -- Start of processing for Remove_Warning_Messages
2024 begin
2025 if Warnings_Detected /= 0 then
2026 declare
2027 Discard : Traverse_Result;
2028 begin
2029 Discard := Check_All_Warnings (N);
2030 end;
2031 end if;
2032 end Remove_Warning_Messages;
2034 ----------------
2035 -- Same_Error --
2036 ----------------
2038 function Same_Error (M1, M2 : Error_Msg_Id) return Boolean is
2039 Msg1 : constant String_Ptr := Errors.Table (M1).Text;
2040 Msg2 : constant String_Ptr := Errors.Table (M2).Text;
2042 Msg2_Len : constant Integer := Msg2'Length;
2043 Msg1_Len : constant Integer := Msg1'Length;
2045 begin
2046 return
2047 Msg1.all = Msg2.all
2048 or else
2049 (Msg1_Len - 10 > Msg2_Len
2050 and then
2051 Msg2.all = Msg1.all (1 .. Msg2_Len)
2052 and then
2053 Msg1 (Msg2_Len + 1 .. Msg2_Len + 10) = ", instance")
2054 or else
2055 (Msg2_Len - 10 > Msg1_Len
2056 and then
2057 Msg1.all = Msg2.all (1 .. Msg1_Len)
2058 and then
2059 Msg2 (Msg1_Len + 1 .. Msg1_Len + 10) = ", instance");
2060 end Same_Error;
2062 -------------------
2063 -- Set_Msg_Blank --
2064 -------------------
2066 procedure Set_Msg_Blank is
2067 begin
2068 if Msglen > 0
2069 and then Msg_Buffer (Msglen) /= ' '
2070 and then Msg_Buffer (Msglen) /= '('
2071 and then not Manual_Quote_Mode
2072 then
2073 Set_Msg_Char (' ');
2074 end if;
2075 end Set_Msg_Blank;
2077 -------------------------------
2078 -- Set_Msg_Blank_Conditional --
2079 -------------------------------
2081 procedure Set_Msg_Blank_Conditional is
2082 begin
2083 if Msglen > 0
2084 and then Msg_Buffer (Msglen) /= ' '
2085 and then Msg_Buffer (Msglen) /= '('
2086 and then Msg_Buffer (Msglen) /= '"'
2087 and then not Manual_Quote_Mode
2088 then
2089 Set_Msg_Char (' ');
2090 end if;
2091 end Set_Msg_Blank_Conditional;
2093 ------------------
2094 -- Set_Msg_Char --
2095 ------------------
2097 procedure Set_Msg_Char (C : Character) is
2098 begin
2100 -- The check for message buffer overflow is needed to deal with cases
2101 -- where insertions get too long (in particular a child unit name can
2102 -- be very long).
2104 if Msglen < Max_Msg_Length then
2105 Msglen := Msglen + 1;
2106 Msg_Buffer (Msglen) := C;
2107 end if;
2108 end Set_Msg_Char;
2110 ------------------------------
2111 -- Set_Msg_Insertion_Column --
2112 ------------------------------
2114 procedure Set_Msg_Insertion_Column is
2115 begin
2116 if Style.RM_Column_Check then
2117 Set_Msg_Str (" in column ");
2118 Set_Msg_Int (Int (Error_Msg_Col) + 1);
2119 end if;
2120 end Set_Msg_Insertion_Column;
2122 ---------------------------------
2123 -- Set_Msg_Insertion_File_Name --
2124 ---------------------------------
2126 procedure Set_Msg_Insertion_File_Name is
2127 begin
2128 if Error_Msg_Name_1 = No_Name then
2129 null;
2131 elsif Error_Msg_Name_1 = Error_Name then
2132 Set_Msg_Blank;
2133 Set_Msg_Str ("<error>");
2135 else
2136 Set_Msg_Blank;
2137 Get_Name_String (Error_Msg_Name_1);
2138 Set_Msg_Quote;
2139 Set_Msg_Name_Buffer;
2140 Set_Msg_Quote;
2141 end if;
2143 -- The following assignments ensure that the second and third percent
2144 -- insertion characters will correspond to the Error_Msg_Name_2 and
2145 -- Error_Msg_Name_3 as required.
2147 Error_Msg_Name_1 := Error_Msg_Name_2;
2148 Error_Msg_Name_2 := Error_Msg_Name_3;
2150 end Set_Msg_Insertion_File_Name;
2152 -----------------------------------
2153 -- Set_Msg_Insertion_Line_Number --
2154 -----------------------------------
2156 procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr) is
2157 Sindex_Loc : Source_File_Index;
2158 Sindex_Flag : Source_File_Index;
2160 begin
2161 Set_Msg_Blank;
2163 if Loc = No_Location then
2164 Set_Msg_Str ("at unknown location");
2166 elsif Loc <= Standard_Location then
2167 Set_Msg_Str ("in package Standard");
2169 if Loc = Standard_ASCII_Location then
2170 Set_Msg_Str (".ASCII");
2171 end if;
2173 else
2174 -- Add "at file-name:" if reference is to other than the source
2175 -- file in which the error message is placed. Note that we check
2176 -- full file names, rather than just the source indexes, to
2177 -- deal with generic instantiations from the current file.
2179 Sindex_Loc := Get_Source_File_Index (Loc);
2180 Sindex_Flag := Get_Source_File_Index (Flag);
2182 if Full_File_Name (Sindex_Loc) /= Full_File_Name (Sindex_Flag) then
2183 Set_Msg_Str ("at ");
2184 Get_Name_String
2185 (Reference_Name (Get_Source_File_Index (Loc)));
2186 Set_Msg_Name_Buffer;
2187 Set_Msg_Char (':');
2189 -- If in current file, add text "at line "
2191 else
2192 Set_Msg_Str ("at line ");
2193 end if;
2195 -- Output line number for reference
2197 Set_Msg_Int (Int (Get_Logical_Line_Number (Loc)));
2199 -- Deal with the instantiation case. We may have a reference to,
2200 -- e.g. a type, that is declared within a generic template, and
2201 -- what we are really referring to is the occurrence in an instance.
2202 -- In this case, the line number of the instantiation is also of
2203 -- interest, and we add a notation:
2205 -- , instance at xxx
2207 -- where xxx is a line number output using this same routine (and
2208 -- the recursion can go further if the instantiation is itself in
2209 -- a generic template).
2211 -- The flag location passed to us in this situation is indeed the
2212 -- line number within the template, but as described in Sinput.L
2213 -- (file sinput-l.ads, section "Handling Generic Instantiations")
2214 -- we can retrieve the location of the instantiation itself from
2215 -- this flag location value.
2217 -- Note: this processing is suppressed if Suppress_Instance_Location
2218 -- is set True. This is used to prevent redundant annotations of the
2219 -- location of the instantiation in the case where we are placing
2220 -- the messages on the instantiation in any case.
2222 if Instantiation (Sindex_Loc) /= No_Location
2223 and then not Suppress_Instance_Location
2224 then
2225 Set_Msg_Str (", instance ");
2226 Set_Msg_Insertion_Line_Number (Instantiation (Sindex_Loc), Flag);
2227 end if;
2228 end if;
2229 end Set_Msg_Insertion_Line_Number;
2231 ----------------------------
2232 -- Set_Msg_Insertion_Name --
2233 ----------------------------
2235 procedure Set_Msg_Insertion_Name is
2236 begin
2237 if Error_Msg_Name_1 = No_Name then
2238 null;
2240 elsif Error_Msg_Name_1 = Error_Name then
2241 Set_Msg_Blank;
2242 Set_Msg_Str ("<error>");
2244 else
2245 Set_Msg_Blank_Conditional;
2246 Get_Unqualified_Decoded_Name_String (Error_Msg_Name_1);
2248 -- Remove %s or %b at end. These come from unit names. If the
2249 -- caller wanted the (unit) or (body), then they would have used
2250 -- the $ insertion character. Certainly no error message should
2251 -- ever have %b or %s explicitly occurring.
2253 if Name_Len > 2
2254 and then Name_Buffer (Name_Len - 1) = '%'
2255 and then (Name_Buffer (Name_Len) = 'b'
2256 or else
2257 Name_Buffer (Name_Len) = 's')
2258 then
2259 Name_Len := Name_Len - 2;
2260 end if;
2262 -- Remove upper case letter at end, again, we should not be getting
2263 -- such names, and what we hope is that the remainder makes sense.
2265 if Name_Len > 1
2266 and then Name_Buffer (Name_Len) in 'A' .. 'Z'
2267 then
2268 Name_Len := Name_Len - 1;
2269 end if;
2271 -- If operator name or character literal name, just print it as is
2272 -- Also print as is if it ends in a right paren (case of x'val(nnn))
2274 if Name_Buffer (1) = '"'
2275 or else Name_Buffer (1) = '''
2276 or else Name_Buffer (Name_Len) = ')'
2277 then
2278 Set_Msg_Name_Buffer;
2280 -- Else output with surrounding quotes in proper casing mode
2282 else
2283 Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
2284 Set_Msg_Quote;
2285 Set_Msg_Name_Buffer;
2286 Set_Msg_Quote;
2287 end if;
2288 end if;
2290 -- The following assignments ensure that the second and third percent
2291 -- insertion characters will correspond to the Error_Msg_Name_2 and
2292 -- Error_Msg_Name_3 as required.
2294 Error_Msg_Name_1 := Error_Msg_Name_2;
2295 Error_Msg_Name_2 := Error_Msg_Name_3;
2297 end Set_Msg_Insertion_Name;
2299 ----------------------------
2300 -- Set_Msg_Insertion_Node --
2301 ----------------------------
2303 procedure Set_Msg_Insertion_Node is
2304 begin
2305 Suppress_Message :=
2306 Error_Msg_Node_1 = Error
2307 or else Error_Msg_Node_1 = Any_Type;
2309 if Error_Msg_Node_1 = Empty then
2310 Set_Msg_Blank_Conditional;
2311 Set_Msg_Str ("<empty>");
2313 elsif Error_Msg_Node_1 = Error then
2314 Set_Msg_Blank;
2315 Set_Msg_Str ("<error>");
2317 elsif Error_Msg_Node_1 = Standard_Void_Type then
2318 Set_Msg_Blank;
2319 Set_Msg_Str ("procedure name");
2321 else
2322 Set_Msg_Blank_Conditional;
2324 -- Skip quotes for operator case
2326 if Nkind (Error_Msg_Node_1) in N_Op then
2327 Set_Msg_Node (Error_Msg_Node_1);
2329 else
2330 Set_Msg_Quote;
2331 Set_Qualification (Error_Msg_Qual_Level, Error_Msg_Node_1);
2332 Set_Msg_Node (Error_Msg_Node_1);
2333 Set_Msg_Quote;
2334 end if;
2335 end if;
2337 -- The following assignment ensures that a second ampersand insertion
2338 -- character will correspond to the Error_Msg_Node_2 parameter.
2340 Error_Msg_Node_1 := Error_Msg_Node_2;
2342 end Set_Msg_Insertion_Node;
2344 -------------------------------------
2345 -- Set_Msg_Insertion_Reserved_Name --
2346 -------------------------------------
2348 procedure Set_Msg_Insertion_Reserved_Name is
2349 begin
2350 Set_Msg_Blank_Conditional;
2351 Get_Name_String (Error_Msg_Name_1);
2352 Set_Msg_Quote;
2353 Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
2354 Set_Msg_Name_Buffer;
2355 Set_Msg_Quote;
2356 end Set_Msg_Insertion_Reserved_Name;
2358 -------------------------------------
2359 -- Set_Msg_Insertion_Reserved_Word --
2360 -------------------------------------
2362 procedure Set_Msg_Insertion_Reserved_Word
2363 (Text : String;
2364 J : in out Integer)
2366 begin
2367 Set_Msg_Blank_Conditional;
2368 Name_Len := 0;
2370 while J <= Text'Last and then Text (J) in 'A' .. 'Z' loop
2371 Name_Len := Name_Len + 1;
2372 Name_Buffer (Name_Len) := Text (J);
2373 J := J + 1;
2374 end loop;
2376 Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
2377 Set_Msg_Quote;
2378 Set_Msg_Name_Buffer;
2379 Set_Msg_Quote;
2380 end Set_Msg_Insertion_Reserved_Word;
2382 --------------------------------------
2383 -- Set_Msg_Insertion_Type_Reference --
2384 --------------------------------------
2386 procedure Set_Msg_Insertion_Type_Reference (Flag : Source_Ptr) is
2387 Ent : Entity_Id;
2389 begin
2390 Set_Msg_Blank;
2392 if Error_Msg_Node_1 = Standard_Void_Type then
2393 Set_Msg_Str ("package or procedure name");
2394 return;
2396 elsif Error_Msg_Node_1 = Standard_Exception_Type then
2397 Set_Msg_Str ("exception name");
2398 return;
2400 elsif Error_Msg_Node_1 = Any_Access
2401 or else Error_Msg_Node_1 = Any_Array
2402 or else Error_Msg_Node_1 = Any_Boolean
2403 or else Error_Msg_Node_1 = Any_Character
2404 or else Error_Msg_Node_1 = Any_Composite
2405 or else Error_Msg_Node_1 = Any_Discrete
2406 or else Error_Msg_Node_1 = Any_Fixed
2407 or else Error_Msg_Node_1 = Any_Integer
2408 or else Error_Msg_Node_1 = Any_Modular
2409 or else Error_Msg_Node_1 = Any_Numeric
2410 or else Error_Msg_Node_1 = Any_Real
2411 or else Error_Msg_Node_1 = Any_Scalar
2412 or else Error_Msg_Node_1 = Any_String
2413 then
2414 Get_Unqualified_Decoded_Name_String (Chars (Error_Msg_Node_1));
2415 Set_Msg_Name_Buffer;
2416 return;
2418 elsif Error_Msg_Node_1 = Universal_Real then
2419 Set_Msg_Str ("type universal real");
2420 return;
2422 elsif Error_Msg_Node_1 = Universal_Integer then
2423 Set_Msg_Str ("type universal integer");
2424 return;
2426 elsif Error_Msg_Node_1 = Universal_Fixed then
2427 Set_Msg_Str ("type universal fixed");
2428 return;
2429 end if;
2431 -- Special case of anonymous array
2433 if Nkind (Error_Msg_Node_1) in N_Entity
2434 and then Is_Array_Type (Error_Msg_Node_1)
2435 and then Present (Related_Array_Object (Error_Msg_Node_1))
2436 then
2437 Set_Msg_Str ("type of ");
2438 Set_Msg_Node (Related_Array_Object (Error_Msg_Node_1));
2439 Set_Msg_Str (" declared");
2440 Set_Msg_Insertion_Line_Number
2441 (Sloc (Related_Array_Object (Error_Msg_Node_1)), Flag);
2442 return;
2443 end if;
2445 -- If we fall through, it is not a special case, so first output
2446 -- the name of the type, preceded by private for a private type
2448 if Is_Private_Type (Error_Msg_Node_1) then
2449 Set_Msg_Str ("private type ");
2450 else
2451 Set_Msg_Str ("type ");
2452 end if;
2454 Ent := Error_Msg_Node_1;
2456 if Is_Internal_Name (Chars (Ent)) then
2457 Unwind_Internal_Type (Ent);
2458 end if;
2460 -- Types in Standard are displayed as "Standard.name"
2462 if Sloc (Ent) <= Standard_Location then
2463 Set_Msg_Quote;
2464 Set_Msg_Str ("Standard.");
2465 Set_Msg_Node (Ent);
2466 Add_Class;
2467 Set_Msg_Quote;
2469 -- Types in other language defined units are displayed as
2470 -- "package-name.type-name"
2472 elsif
2473 Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (Ent)))
2474 then
2475 Get_Unqualified_Decoded_Name_String
2476 (Unit_Name (Get_Source_Unit (Ent)));
2477 Name_Len := Name_Len - 2;
2478 Set_Msg_Quote;
2479 Set_Casing (Mixed_Case);
2480 Set_Msg_Name_Buffer;
2481 Set_Msg_Char ('.');
2482 Set_Casing (Mixed_Case);
2483 Set_Msg_Node (Ent);
2484 Add_Class;
2485 Set_Msg_Quote;
2487 -- All other types display as "type name" defined at line xxx
2488 -- possibly qualified if qualification is requested.
2490 else
2491 Set_Msg_Quote;
2492 Set_Qualification (Error_Msg_Qual_Level, Ent);
2493 Set_Msg_Node (Ent);
2494 Add_Class;
2495 Set_Msg_Quote;
2496 end if;
2498 -- If the original type did not come from a predefined
2499 -- file, add the location where the type was defined.
2501 if Sloc (Error_Msg_Node_1) > Standard_Location
2502 and then
2503 not Is_Predefined_File_Name
2504 (Unit_File_Name (Get_Source_Unit (Error_Msg_Node_1)))
2505 then
2506 Set_Msg_Str (" defined");
2507 Set_Msg_Insertion_Line_Number (Sloc (Error_Msg_Node_1), Flag);
2509 -- If it did come from a predefined file, deal with the case where
2510 -- this was a file with a generic instantiation from elsewhere.
2512 else
2513 if Sloc (Error_Msg_Node_1) > Standard_Location then
2514 declare
2515 Iloc : constant Source_Ptr :=
2516 Instantiation_Location (Sloc (Error_Msg_Node_1));
2518 begin
2519 if Iloc /= No_Location
2520 and then not Suppress_Instance_Location
2521 then
2522 Set_Msg_Str (" from instance");
2523 Set_Msg_Insertion_Line_Number (Iloc, Flag);
2524 end if;
2525 end;
2526 end if;
2527 end if;
2529 end Set_Msg_Insertion_Type_Reference;
2531 ----------------------------
2532 -- Set_Msg_Insertion_Uint --
2533 ----------------------------
2535 procedure Set_Msg_Insertion_Uint is
2536 begin
2537 Set_Msg_Blank;
2538 UI_Image (Error_Msg_Uint_1);
2540 for J in 1 .. UI_Image_Length loop
2541 Set_Msg_Char (UI_Image_Buffer (J));
2542 end loop;
2544 -- The following assignment ensures that a second carret insertion
2545 -- character will correspond to the Error_Msg_Uint_2 parameter.
2547 Error_Msg_Uint_1 := Error_Msg_Uint_2;
2548 end Set_Msg_Insertion_Uint;
2550 ---------------------------------
2551 -- Set_Msg_Insertion_Unit_Name --
2552 ---------------------------------
2554 procedure Set_Msg_Insertion_Unit_Name is
2555 begin
2556 if Error_Msg_Unit_1 = No_Name then
2557 null;
2559 elsif Error_Msg_Unit_1 = Error_Name then
2560 Set_Msg_Blank;
2561 Set_Msg_Str ("<error>");
2563 else
2564 Get_Unit_Name_String (Error_Msg_Unit_1);
2565 Set_Msg_Blank;
2566 Set_Msg_Quote;
2567 Set_Msg_Name_Buffer;
2568 Set_Msg_Quote;
2569 end if;
2571 -- The following assignment ensures that a second percent insertion
2572 -- character will correspond to the Error_Msg_Unit_2 parameter.
2574 Error_Msg_Unit_1 := Error_Msg_Unit_2;
2576 end Set_Msg_Insertion_Unit_Name;
2578 -----------------
2579 -- Set_Msg_Int --
2580 -----------------
2582 procedure Set_Msg_Int (Line : Int) is
2583 begin
2584 if Line > 9 then
2585 Set_Msg_Int (Line / 10);
2586 end if;
2588 Set_Msg_Char (Character'Val (Character'Pos ('0') + (Line rem 10)));
2589 end Set_Msg_Int;
2591 -------------------------
2592 -- Set_Msg_Name_Buffer --
2593 -------------------------
2595 procedure Set_Msg_Name_Buffer is
2596 begin
2597 for J in 1 .. Name_Len loop
2598 Set_Msg_Char (Name_Buffer (J));
2599 end loop;
2600 end Set_Msg_Name_Buffer;
2602 ------------------
2603 -- Set_Msg_Node --
2604 ------------------
2606 procedure Set_Msg_Node (Node : Node_Id) is
2607 Ent : Entity_Id;
2608 Nam : Name_Id;
2610 begin
2611 if Nkind (Node) = N_Designator then
2612 Set_Msg_Node (Name (Node));
2613 Set_Msg_Char ('.');
2614 Set_Msg_Node (Identifier (Node));
2615 return;
2617 elsif Nkind (Node) = N_Defining_Program_Unit_Name then
2618 Set_Msg_Node (Name (Node));
2619 Set_Msg_Char ('.');
2620 Set_Msg_Node (Defining_Identifier (Node));
2621 return;
2623 elsif Nkind (Node) = N_Selected_Component then
2624 Set_Msg_Node (Prefix (Node));
2625 Set_Msg_Char ('.');
2626 Set_Msg_Node (Selector_Name (Node));
2627 return;
2628 end if;
2630 -- The only remaining possibilities are identifiers, defining
2631 -- identifiers, pragmas, and pragma argument associations, i.e.
2632 -- nodes that have a Chars field.
2634 -- Internal names generally represent something gone wrong. An exception
2635 -- is the case of internal type names, where we try to find a reasonable
2636 -- external representation for the external name
2638 if Is_Internal_Name (Chars (Node))
2639 and then
2640 ((Is_Entity_Name (Node)
2641 and then Present (Entity (Node))
2642 and then Is_Type (Entity (Node)))
2643 or else
2644 (Nkind (Node) = N_Defining_Identifier and then Is_Type (Node)))
2645 then
2646 if Nkind (Node) = N_Identifier then
2647 Ent := Entity (Node);
2648 else
2649 Ent := Node;
2650 end if;
2652 Unwind_Internal_Type (Ent);
2653 Nam := Chars (Ent);
2655 else
2656 Nam := Chars (Node);
2657 end if;
2659 -- At this stage, the name to output is in Nam
2661 Get_Unqualified_Decoded_Name_String (Nam);
2663 -- Remove trailing upper case letters from the name (useful for
2664 -- dealing with some cases of internal names.
2666 while Name_Len > 1 and then Name_Buffer (Name_Len) in 'A' .. 'Z' loop
2667 Name_Len := Name_Len - 1;
2668 end loop;
2670 -- If we have any of the names from standard that start with the
2671 -- characters "any " (e.g. Any_Type), then kill the message since
2672 -- almost certainly it is a junk cascaded message.
2674 if Name_Len > 4
2675 and then Name_Buffer (1 .. 4) = "any "
2676 then
2677 Kill_Message := True;
2678 end if;
2680 -- Now we have to set the proper case. If we have a source location
2681 -- then do a check to see if the name in the source is the same name
2682 -- as the name in the Names table, except for possible differences
2683 -- in case, which is the case when we can copy from the source.
2685 declare
2686 Src_Loc : constant Source_Ptr := Sloc (Error_Msg_Node_1);
2687 Sbuffer : Source_Buffer_Ptr;
2688 Ref_Ptr : Integer;
2689 Src_Ptr : Source_Ptr;
2691 begin
2692 Ref_Ptr := 1;
2693 Src_Ptr := Src_Loc;
2695 -- Determine if the reference we are dealing with corresponds
2696 -- to text at the point of the error reference. This will often
2697 -- be the case for simple identifier references, and is the case
2698 -- where we can copy the spelling from the source.
2700 if Src_Loc /= No_Location
2701 and then Src_Loc > Standard_Location
2702 then
2703 Sbuffer := Source_Text (Get_Source_File_Index (Src_Loc));
2705 while Ref_Ptr <= Name_Len loop
2706 exit when
2707 Fold_Lower (Sbuffer (Src_Ptr)) /=
2708 Fold_Lower (Name_Buffer (Ref_Ptr));
2709 Ref_Ptr := Ref_Ptr + 1;
2710 Src_Ptr := Src_Ptr + 1;
2711 end loop;
2712 end if;
2714 -- If we get through the loop without a mismatch, then output
2715 -- the name the way it is spelled in the source program
2717 if Ref_Ptr > Name_Len then
2718 Src_Ptr := Src_Loc;
2720 for J in 1 .. Name_Len loop
2721 Name_Buffer (J) := Sbuffer (Src_Ptr);
2722 Src_Ptr := Src_Ptr + 1;
2723 end loop;
2725 -- Otherwise set the casing using the default identifier casing
2727 else
2728 Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
2729 end if;
2730 end;
2732 Set_Msg_Name_Buffer;
2733 Add_Class;
2735 -- Add 'Class if class wide type
2737 if Class_Flag then
2738 Set_Msg_Char (''');
2739 Get_Name_String (Name_Class);
2740 Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
2741 Set_Msg_Name_Buffer;
2742 end if;
2743 end Set_Msg_Node;
2745 -------------------
2746 -- Set_Msg_Quote --
2747 -------------------
2749 procedure Set_Msg_Quote is
2750 begin
2751 if not Manual_Quote_Mode then
2752 Set_Msg_Char ('"');
2753 end if;
2754 end Set_Msg_Quote;
2756 -----------------
2757 -- Set_Msg_Str --
2758 -----------------
2760 procedure Set_Msg_Str (Text : String) is
2761 begin
2762 for J in Text'Range loop
2763 Set_Msg_Char (Text (J));
2764 end loop;
2765 end Set_Msg_Str;
2767 ------------------
2768 -- Set_Msg_Text --
2769 ------------------
2771 procedure Set_Msg_Text (Text : String; Flag : Source_Ptr) is
2772 C : Character; -- Current character
2773 P : Natural; -- Current index;
2775 begin
2776 Manual_Quote_Mode := False;
2777 Is_Unconditional_Msg := False;
2778 Msglen := 0;
2779 Flag_Source := Get_Source_File_Index (Flag);
2780 P := Text'First;
2782 while P <= Text'Last loop
2783 C := Text (P);
2784 P := P + 1;
2786 -- Check for insertion character
2788 if C = '%' then
2789 Set_Msg_Insertion_Name;
2791 elsif C = '$' then
2792 Set_Msg_Insertion_Unit_Name;
2794 elsif C = '{' then
2795 Set_Msg_Insertion_File_Name;
2797 elsif C = '}' then
2798 Set_Msg_Insertion_Type_Reference (Flag);
2800 elsif C = '*' then
2801 Set_Msg_Insertion_Reserved_Name;
2803 elsif C = '&' then
2804 Set_Msg_Insertion_Node;
2806 elsif C = '#' then
2807 Set_Msg_Insertion_Line_Number (Error_Msg_Sloc, Flag);
2809 elsif C = '\' then
2810 Continuation := True;
2812 elsif C = '@' then
2813 Set_Msg_Insertion_Column;
2815 elsif C = '^' then
2816 Set_Msg_Insertion_Uint;
2818 elsif C = '`' then
2819 Manual_Quote_Mode := not Manual_Quote_Mode;
2820 Set_Msg_Char ('"');
2822 elsif C = '!' then
2823 Is_Unconditional_Msg := True;
2825 elsif C = '?' then
2826 null;
2828 elsif C = ''' then
2829 Set_Msg_Char (Text (P));
2830 P := P + 1;
2832 -- Upper case letter (start of reserved word if 2 or more)
2834 elsif C in 'A' .. 'Z'
2835 and then P <= Text'Last
2836 and then Text (P) in 'A' .. 'Z'
2837 then
2838 P := P - 1;
2839 Set_Msg_Insertion_Reserved_Word (Text, P);
2841 -- Normal character with no special treatment
2843 else
2844 Set_Msg_Char (C);
2845 end if;
2847 end loop;
2848 end Set_Msg_Text;
2850 ------------------------------
2851 -- Set_Next_Non_Deleted_Msg --
2852 ------------------------------
2854 procedure Set_Next_Non_Deleted_Msg (E : in out Error_Msg_Id) is
2855 begin
2856 if E = No_Error_Msg then
2857 return;
2859 else
2860 loop
2861 E := Errors.Table (E).Next;
2862 exit when E = No_Error_Msg or else not Errors.Table (E).Deleted;
2863 end loop;
2864 end if;
2865 end Set_Next_Non_Deleted_Msg;
2867 ----------------
2868 -- Set_Posted --
2869 ----------------
2871 procedure Set_Posted (N : Node_Id) is
2872 P : Node_Id;
2874 begin
2875 -- We always set Error_Posted on the node itself
2877 Set_Error_Posted (N);
2879 -- If it is a subexpression, then set Error_Posted on parents
2880 -- up to and including the first non-subexpression construct. This
2881 -- helps avoid cascaded error messages within a single expression.
2883 P := N;
2884 loop
2885 P := Parent (P);
2886 exit when No (P);
2887 Set_Error_Posted (P);
2888 exit when Nkind (P) not in N_Subexpr;
2889 end loop;
2890 end Set_Posted;
2892 -----------------------
2893 -- Set_Qualification --
2894 -----------------------
2896 procedure Set_Qualification (N : Nat; E : Entity_Id) is
2897 begin
2898 if N /= 0 and then Scope (E) /= Standard_Standard then
2899 Set_Qualification (N - 1, Scope (E));
2900 Set_Msg_Node (Scope (E));
2901 Set_Msg_Char ('.');
2902 end if;
2903 end Set_Qualification;
2905 ---------------------------
2906 -- Set_Warnings_Mode_Off --
2907 ---------------------------
2909 procedure Set_Warnings_Mode_Off (Loc : Source_Ptr) is
2910 begin
2911 -- Don't bother with entries from instantiation copies, since we
2912 -- will already have a copy in the template, which is what matters
2914 if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
2915 return;
2916 end if;
2918 -- If last entry in table already covers us, this is a redundant
2919 -- pragma Warnings (Off) and can be ignored. This also handles the
2920 -- case where all warnings are suppressed by command line switch.
2922 if Warnings.Last >= Warnings.First
2923 and then Warnings.Table (Warnings.Last).Start <= Loc
2924 and then Loc <= Warnings.Table (Warnings.Last).Stop
2925 then
2926 return;
2928 -- Otherwise establish a new entry, extending from the location of
2929 -- the pragma to the end of the current source file. This ending
2930 -- point will be adjusted by a subsequent pragma Warnings (On).
2932 else
2933 Warnings.Increment_Last;
2934 Warnings.Table (Warnings.Last).Start := Loc;
2935 Warnings.Table (Warnings.Last).Stop :=
2936 Source_Last (Current_Source_File);
2937 end if;
2938 end Set_Warnings_Mode_Off;
2940 --------------------------
2941 -- Set_Warnings_Mode_On --
2942 --------------------------
2944 procedure Set_Warnings_Mode_On (Loc : Source_Ptr) is
2945 begin
2946 -- Don't bother with entries from instantiation copies, since we
2947 -- will already have a copy in the template, which is what matters
2949 if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
2950 return;
2951 end if;
2953 -- Nothing to do unless command line switch to suppress all warnings
2954 -- is off, and the last entry in the warnings table covers this
2955 -- pragma Warnings (On), in which case adjust the end point.
2957 if (Warnings.Last >= Warnings.First
2958 and then Warnings.Table (Warnings.Last).Start <= Loc
2959 and then Loc <= Warnings.Table (Warnings.Last).Stop)
2960 and then Warning_Mode /= Suppress
2961 then
2962 Warnings.Table (Warnings.Last).Stop := Loc;
2963 end if;
2964 end Set_Warnings_Mode_On;
2966 ----------------------
2967 -- Test_Warning_Msg --
2968 ----------------------
2970 procedure Test_Warning_Msg (Msg : String) is
2971 begin
2972 if Msg'Length > 7 and then Msg (1 .. 7) = "(style)" then
2973 Is_Warning_Msg := True;
2974 return;
2975 end if;
2977 for J in Msg'Range loop
2978 if Msg (J) = '?'
2979 and then (J = Msg'First or else Msg (J - 1) /= ''')
2980 then
2981 Is_Warning_Msg := True;
2982 return;
2983 end if;
2984 end loop;
2986 Is_Warning_Msg := False;
2987 end Test_Warning_Msg;
2989 --------------------------
2990 -- Unwind_Internal_Type --
2991 --------------------------
2993 procedure Unwind_Internal_Type (Ent : in out Entity_Id) is
2994 Derived : Boolean := False;
2995 Mchar : Character;
2996 Old_Ent : Entity_Id;
2998 begin
2999 -- Undo placement of a quote, since we will put it back later
3001 Mchar := Msg_Buffer (Msglen);
3003 if Mchar = '"' then
3004 Msglen := Msglen - 1;
3005 end if;
3007 -- The loop here deals with recursive types, we are trying to
3008 -- find a related entity that is not an implicit type. Note
3009 -- that the check with Old_Ent stops us from getting "stuck".
3010 -- Also, we don't output the "type derived from" message more
3011 -- than once in the case where we climb up multiple levels.
3013 loop
3014 Old_Ent := Ent;
3016 -- Implicit access type, use directly designated type
3018 if Is_Access_Type (Ent) then
3019 Set_Msg_Str ("access to ");
3020 Ent := Directly_Designated_Type (Ent);
3022 -- Classwide type
3024 elsif Is_Class_Wide_Type (Ent) then
3025 Class_Flag := True;
3026 Ent := Root_Type (Ent);
3028 -- Use base type if this is a subtype
3030 elsif Ent /= Base_Type (Ent) then
3031 Buffer_Remove ("type ");
3033 -- Avoid duplication "subtype of subtype of", and also replace
3034 -- "derived from subtype of" simply by "derived from"
3036 if not Buffer_Ends_With ("subtype of ")
3037 and then not Buffer_Ends_With ("derived from ")
3038 then
3039 Set_Msg_Str ("subtype of ");
3040 end if;
3042 Ent := Base_Type (Ent);
3044 -- If this is a base type with a first named subtype, use the
3045 -- first named subtype instead. This is not quite accurate in
3046 -- all cases, but it makes too much noise to be accurate and
3047 -- add 'Base in all cases. Note that we only do this is the
3048 -- first named subtype is not itself an internal name. This
3049 -- avoids the obvious loop (subtype->basetype->subtype) which
3050 -- would otherwise occur!)
3052 elsif Present (Freeze_Node (Ent))
3053 and then Present (First_Subtype_Link (Freeze_Node (Ent)))
3054 and then
3055 not Is_Internal_Name
3056 (Chars (First_Subtype_Link (Freeze_Node (Ent))))
3057 then
3058 Ent := First_Subtype_Link (Freeze_Node (Ent));
3060 -- Otherwise use root type
3062 else
3063 if not Derived then
3064 Buffer_Remove ("type ");
3066 -- Test for "subtype of type derived from" which seems
3067 -- excessive and is replaced by simply "type derived from"
3069 Buffer_Remove ("subtype of");
3071 -- Avoid duplication "type derived from type derived from"
3073 if not Buffer_Ends_With ("type derived from ") then
3074 Set_Msg_Str ("type derived from ");
3075 end if;
3077 Derived := True;
3078 end if;
3080 Ent := Etype (Ent);
3081 end if;
3083 -- If we are stuck in a loop, get out and settle for the internal
3084 -- name after all. In this case we set to kill the message if it
3085 -- is not the first error message (we really try hard not to show
3086 -- the dirty laundry of the implementation to the poor user!)
3088 if Ent = Old_Ent then
3089 Kill_Message := True;
3090 exit;
3091 end if;
3093 -- Get out if we finally found a non-internal name to use
3095 exit when not Is_Internal_Name (Chars (Ent));
3096 end loop;
3098 if Mchar = '"' then
3099 Set_Msg_Char ('"');
3100 end if;
3102 end Unwind_Internal_Type;
3104 -------------------------
3105 -- Warnings_Suppressed --
3106 -------------------------
3108 function Warnings_Suppressed (Loc : Source_Ptr) return Boolean is
3109 begin
3110 for J in Warnings.First .. Warnings.Last loop
3111 if Warnings.Table (J).Start <= Loc
3112 and then Loc <= Warnings.Table (J).Stop
3113 then
3114 return True;
3115 end if;
3116 end loop;
3118 return False;
3119 end Warnings_Suppressed;
3121 end Errout;