1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2021, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 -- Warning: Error messages can be generated during Gigi processing by direct
27 -- calls to error message routines, so it is essential that the processing
28 -- in this body be consistent with the requirements for the Gigi processing
29 -- environment, and that in particular, no disallowed table expansion is
32 with Atree
; use Atree
;
33 with Casing
; use Casing
;
34 with Csets
; use Csets
;
35 with Debug
; use Debug
;
36 with Err_Vars
; use Err_Vars
;
37 with Fname
; use Fname
;
38 with Namet
; use Namet
;
40 with Output
; use Output
;
41 with Sinput
; use Sinput
;
42 with Snames
; use Snames
;
43 with Stringt
; use Stringt
;
45 with Uintp
; use Uintp
;
46 with Widechar
; use Widechar
;
48 package body Erroutc
is
50 -----------------------
51 -- Local Subprograms --
52 -----------------------
54 function Sloc_In_Range
(Loc
, Start
, Stop
: Source_Ptr
) return Boolean;
55 -- Return whether Loc is in the range Start .. Stop, taking instantiation
56 -- locations of Loc into account. This is useful for suppressing warnings
57 -- from generic instantiations by using pragma Warnings around generic
58 -- instances, as needed in GNATprove.
64 procedure Add_Class
is
69 Get_Name_String
(Name_Class
);
70 Set_Casing
(Identifier_Casing
(Flag_Source
));
75 ----------------------
76 -- Buffer_Ends_With --
77 ----------------------
79 function Buffer_Ends_With
(C
: Character) return Boolean is
81 return Msglen
> 0 and then Msg_Buffer
(Msglen
) = C
;
84 function Buffer_Ends_With
(S
: String) return Boolean is
85 Len
: constant Natural := S
'Length;
88 and then Msg_Buffer
(Msglen
- Len
) = ' '
89 and then Msg_Buffer
(Msglen
- Len
+ 1 .. Msglen
) = S
;
96 procedure Buffer_Remove
(C
: Character) is
98 if Buffer_Ends_With
(C
) then
103 procedure Buffer_Remove
(S
: String) is
105 if Buffer_Ends_With
(S
) then
106 Msglen
:= Msglen
- S
'Length;
110 -----------------------------
111 -- Check_Duplicate_Message --
112 -----------------------------
114 procedure Check_Duplicate_Message
(M1
, M2
: Error_Msg_Id
) is
115 L1
, L2
: Error_Msg_Id
;
116 N1
, N2
: Error_Msg_Id
;
118 procedure Delete_Msg
(Delete
, Keep
: Error_Msg_Id
);
119 -- Called to delete message Delete, keeping message Keep. Marks msg
120 -- Delete and all its continuations with deleted flag set to True.
121 -- Also makes sure that for the error messages that are retained the
122 -- preferred message is the one retained (we prefer the shorter one in
123 -- the case where one has an Instance tag). Note that we always know
124 -- that Keep has at least as many continuations as Delete (since we
125 -- always delete the shorter sequence).
131 procedure Delete_Msg
(Delete
, Keep
: Error_Msg_Id
) is
139 Errors
.Table
(D
).Deleted
:= True;
141 -- Adjust error message count
143 if Errors
.Table
(D
).Info
then
145 if Errors
.Table
(D
).Warn
then
146 Warning_Info_Messages
:= Warning_Info_Messages
- 1;
147 Warnings_Detected
:= Warnings_Detected
- 1;
149 Report_Info_Messages
:= Report_Info_Messages
- 1;
152 elsif Errors
.Table
(D
).Warn
or else Errors
.Table
(D
).Style
then
153 Warnings_Detected
:= Warnings_Detected
- 1;
155 -- Note: we do not need to decrement Warnings_Treated_As_Errors
156 -- because this only gets incremented if we actually output the
157 -- message, which we won't do if we are deleting it here!
159 elsif Errors
.Table
(D
).Check
then
160 Check_Messages
:= Check_Messages
- 1;
163 Total_Errors_Detected
:= Total_Errors_Detected
- 1;
165 if Errors
.Table
(D
).Serious
then
166 Serious_Errors_Detected
:= Serious_Errors_Detected
- 1;
170 -- Substitute shorter of the two error messages
172 if Errors
.Table
(K
).Text
'Length > Errors
.Table
(D
).Text
'Length then
173 Errors
.Table
(K
).Text
:= Errors
.Table
(D
).Text
;
176 D
:= Errors
.Table
(D
).Next
;
177 K
:= Errors
.Table
(K
).Next
;
179 if D
= No_Error_Msg
or else not Errors
.Table
(D
).Msg_Cont
then
185 -- Start of processing for Check_Duplicate_Message
188 -- Both messages must be non-continuation messages and not deleted
190 if Errors
.Table
(M1
).Msg_Cont
191 or else Errors
.Table
(M2
).Msg_Cont
192 or else Errors
.Table
(M1
).Deleted
193 or else Errors
.Table
(M2
).Deleted
198 -- Definitely not equal if message text does not match
200 if not Same_Error
(M1
, M2
) then
204 -- Same text. See if all continuations are also identical
210 N1
:= Errors
.Table
(L1
).Next
;
211 N2
:= Errors
.Table
(L2
).Next
;
213 -- If M1 continuations have run out, we delete M1, either the
214 -- messages have the same number of continuations, or M2 has
215 -- more and we prefer the one with more anyway.
217 if N1
= No_Error_Msg
or else not Errors
.Table
(N1
).Msg_Cont
then
221 -- If M2 continuations have run out, we delete M2
223 elsif N2
= No_Error_Msg
or else not Errors
.Table
(N2
).Msg_Cont
then
227 -- Otherwise see if continuations are the same, if not, keep both
228 -- sequences, a curious case, but better to keep everything.
230 elsif not Same_Error
(N1
, N2
) then
233 -- If continuations are the same, continue scan
240 end Check_Duplicate_Message
;
242 ------------------------
243 -- Compilation_Errors --
244 ------------------------
246 function Compilation_Errors
return Boolean is
247 Warnings_Count
: constant Int
248 := Warnings_Detected
- Warning_Info_Messages
;
250 if Total_Errors_Detected
/= 0 then
253 elsif Warnings_Treated_As_Errors
/= 0 then
256 -- We should never treat warnings that originate from a
257 -- Compile_Time_Warning pragma as an error. Warnings_Count is the sum
258 -- of both "normal" and Compile_Time_Warning warnings. This means that
259 -- there are only one or more non-Compile_Time_Warning warnings when
260 -- Warnings_Count is greater than Count_Compile_Time_Pragma_Warnings.
262 elsif Warning_Mode
= Treat_As_Error
263 and then Warnings_Count
> Count_Compile_Time_Pragma_Warnings
269 end Compilation_Errors
;
271 ----------------------------------------
272 -- Count_Compile_Time_Pragma_Warnings --
273 ----------------------------------------
275 function Count_Compile_Time_Pragma_Warnings
return Int
is
278 for J
in 1 .. Errors
.Last
loop
280 if Errors
.Table
(J
).Warn
281 and then Errors
.Table
(J
).Compile_Time_Pragma
282 and then not Errors
.Table
(J
).Deleted
284 Result
:= Result
+ 1;
289 end Count_Compile_Time_Pragma_Warnings
;
295 procedure Debug_Output
(N
: Node_Id
) is
298 Write_Str
("*** following error message posted on node id = #");
309 procedure dmsg
(Id
: Error_Msg_Id
) is
310 E
: Error_Msg_Object
renames Errors
.Table
(Id
);
313 w
("Dumping error message, Id = ", Int
(Id
));
314 w
(" Text = ", E
.Text
.all);
315 w
(" Next = ", Int
(E
.Next
));
316 w
(" Prev = ", Int
(E
.Prev
));
317 w
(" Sfile = ", Int
(E
.Sfile
));
321 Write_Location
(E
.Sptr
.Ptr
); -- ??? Do not write the full span for now
326 Write_Location
(E
.Optr
);
329 w
(" Line = ", Int
(E
.Line
));
330 w
(" Col = ", Int
(E
.Col
));
331 w
(" Warn = ", E
.Warn
);
332 w
(" Warn_Err = ", E
.Warn_Err
);
333 w
(" Warn_Chr = '" & E
.Warn_Chr
& ''');
334 w
(" Style = ", E
.Style
);
335 w
(" Serious = ", E
.Serious
);
336 w
(" Uncond = ", E
.Uncond
);
337 w
(" Msg_Cont = ", E
.Msg_Cont
);
338 w
(" Deleted = ", E
.Deleted
);
339 w
(" Node = ", Int
(E
.Node
));
348 function Get_Location
(E
: Error_Msg_Id
) return Source_Ptr
is
350 return Errors
.Table
(E
).Sptr
.Ptr
;
357 function Get_Msg_Id
return Error_Msg_Id
is
362 ---------------------
363 -- Get_Warning_Tag --
364 ---------------------
366 function Get_Warning_Tag
(Id
: Error_Msg_Id
) return String is
367 Warn
: constant Boolean := Errors
.Table
(Id
).Warn
;
368 Warn_Chr
: constant Character := Errors
.Table
(Id
).Warn_Chr
;
370 if Warn
and then Warn_Chr
/= ' ' then
371 if Warn_Chr
= '?' then
372 return "[enabled by default]";
373 elsif Warn_Chr
= '*' then
374 return "[restriction warning]";
375 elsif Warn_Chr
= '$' then
377 elsif Warn_Chr
in 'a' .. 'z' then
378 return "[-gnatw" & Warn_Chr
& ']';
379 else pragma Assert
(Warn_Chr
in 'A' .. 'Z');
380 return "[-gnatw." & Fold_Lower
(Warn_Chr
) & ']';
391 function Matches
(S
: String; P
: String) return Boolean is
392 Slast
: constant Natural := S
'Last;
393 PLast
: constant Natural := P
'Last;
395 SPtr
: Natural := S
'First;
396 PPtr
: Natural := P
'First;
399 -- Loop advancing through characters of string and pattern
404 -- Return True if pattern is a single asterisk
406 if PPtr
= PLast
and then P
(PPtr
) = '*' then
409 -- Return True if both pattern and string exhausted
411 elsif PPtr
> PLast
and then SPtr
> Slast
then
414 -- Return False, if one exhausted and not the other
416 elsif PPtr
> PLast
or else SPtr
> Slast
then
419 -- Case where pattern starts with asterisk
421 elsif P
(PPtr
) = '*' then
423 -- Try all possible starting positions in S for match with the
424 -- remaining characters of the pattern. This is the recursive
425 -- call that implements the scanner backup.
427 for J
in SPtr
.. Slast
loop
428 if Matches
(S
(J
.. Slast
), P
(PPtr
+ 1 .. PLast
)) then
435 -- Dealt with end of string and *, advance if we have a match
437 elsif Fold_Lower
(S
(SPtr
)) = Fold_Lower
(P
(PPtr
)) then
441 -- If first characters do not match, that's decisive
449 -----------------------
450 -- Output_Error_Msgs --
451 -----------------------
453 procedure Output_Error_Msgs
(E
: in out Error_Msg_Id
) is
459 Mult_Flags
: Boolean := False;
464 -- Skip deleted messages at start
466 if Errors
.Table
(S
).Deleted
then
467 Set_Next_Non_Deleted_Msg
(S
);
470 -- Figure out if we will place more than one error flag on this line
473 while T
/= No_Error_Msg
474 and then Errors
.Table
(T
).Line
= Errors
.Table
(E
).Line
475 and then Errors
.Table
(T
).Sfile
= Errors
.Table
(E
).Sfile
477 if Errors
.Table
(T
).Sptr
.Ptr
> Errors
.Table
(E
).Sptr
.Ptr
then
481 Set_Next_Non_Deleted_Msg
(T
);
484 -- Output the error flags. The circuit here makes sure that the tab
485 -- characters in the original line are properly accounted for. The
486 -- eight blanks at the start are to match the line number.
488 if not Debug_Flag_2
then
490 P
:= Line_Start
(Errors
.Table
(E
).Sptr
.Ptr
);
493 -- Loop through error messages for this line to place flags
496 while T
/= No_Error_Msg
497 and then Errors
.Table
(T
).Line
= Errors
.Table
(E
).Line
498 and then Errors
.Table
(T
).Sfile
= Errors
.Table
(E
).Sfile
501 Src
: Source_Buffer_Ptr
502 renames Source_Text
(Errors
.Table
(T
).Sfile
);
505 -- Loop to output blanks till current flag position
507 while P
< Errors
.Table
(T
).Sptr
.Ptr
loop
509 -- Horizontal tab case, just echo the tab
511 if Src
(P
) = ASCII
.HT
then
512 Write_Char
(ASCII
.HT
);
515 -- Deal with wide character case, but don't include brackets
516 -- notation in this circuit, since we know that this will
517 -- display unencoded (no one encodes brackets notation).
520 and then Is_Start_Of_Wide_Char
(Src
, P
)
525 -- Normal non-wide character case (or bracket)
533 -- Output flag (unless already output, this happens if more
534 -- than one error message occurs at the same flag position).
536 if P
= Errors
.Table
(T
).Sptr
.Ptr
then
537 if (Flag_Num
= 1 and then not Mult_Flags
)
543 (Character'Val (Character'Pos ('0') + Flag_Num
));
546 -- Skip past the corresponding source text character
548 -- Horizontal tab case, we output a flag at the tab position
549 -- so now we output a tab to match up with the text.
551 if Src
(P
) = ASCII
.HT
then
552 Write_Char
(ASCII
.HT
);
555 -- Skip wide character other than left bracket
558 and then Is_Start_Of_Wide_Char
(Src
, P
)
562 -- Skip normal non-wide character case (or bracket)
570 Set_Next_Non_Deleted_Msg
(T
);
571 Flag_Num
:= Flag_Num
+ 1;
577 -- Now output the error messages
580 while T
/= No_Error_Msg
581 and then Errors
.Table
(T
).Line
= Errors
.Table
(E
).Line
582 and then Errors
.Table
(T
).Sfile
= Errors
.Table
(E
).Sfile
588 while Column
< 74 loop
596 Set_Next_Non_Deleted_Msg
(T
);
600 end Output_Error_Msgs
;
602 ------------------------
603 -- Output_Line_Number --
604 ------------------------
606 procedure Output_Line_Number
(L
: Logical_Line_Number
) is
607 D
: Int
; -- next digit
608 C
: Character; -- next character
609 Z
: Boolean; -- flag for zero suppress
610 N
, M
: Int
; -- temporaries
613 if L
= No_Line_Number
then
634 C
:= Character'Val (D
+ 48);
642 end Output_Line_Number
;
644 ---------------------
645 -- Output_Msg_Text --
646 ---------------------
648 procedure Output_Msg_Text
(E
: Error_Msg_Id
) is
649 Offs
: constant Nat
:= Column
- 1;
650 -- Offset to start of message, used for continuations
653 -- Maximum characters to output on next line
656 -- Maximum total length of lines
658 E_Msg
: Error_Msg_Object
renames Errors
.Table
(E
);
659 Text
: constant String_Ptr
:= E_Msg
.Text
;
663 Tag
: constant String := Get_Warning_Tag
(E
);
668 -- Postfix warning tag to message if needed
670 if Tag
/= "" and then Warning_Doc_Switch
then
671 if Include_Subprogram_In_Messages
then
674 (Subprogram_Name_Ptr (E_Msg.Node) &
675 ": " & Text.all & ' ' & Tag);
677 Txt := new String'(Text
.all & ' ' & Tag
);
680 elsif Include_Subprogram_In_Messages
681 and then (E_Msg
.Warn
or else E_Msg
.Style
)
684 new String'(Subprogram_Name_Ptr (E_Msg.Node) & ": " & Text.all);
689 -- If -gnatdF is used, continuation messages follow the main message
690 -- with only an indentation of two space characters, without repeating
693 if Debug_Flag_FF and then E_Msg.Msg_Cont then
696 -- For info messages, prefix message with "info: "
698 elsif E_Msg.Info then
699 Txt := new String'(SGR_Note
& "info: " & SGR_Reset
& Txt
.all);
701 -- Warning treated as error
703 elsif E_Msg
.Warn_Err
then
705 -- We prefix with "error:" rather than warning: and postfix
706 -- [warning-as-error] at the end.
708 Warnings_Treated_As_Errors
:= Warnings_Treated_As_Errors
+ 1;
709 Txt
:= new String'(SGR_Error & "error: " & SGR_Reset
710 & Txt.all & " [warning-as-error]");
712 -- Normal warning, prefix with "warning: "
714 elsif E_Msg.Warn then
715 Txt := new String'(SGR_Warning
& "warning: " & SGR_Reset
& Txt
.all);
717 -- No prefix needed for style message, "(style)" is there already,
718 -- although not necessarily in first position if -gnatdJ is used.
720 elsif E_Msg
.Style
then
721 if Txt
(Txt
'First .. Txt
'First + 6) = "(style)" then
722 Txt
:= new String'(SGR_Warning & "(style)" & SGR_Reset
723 & Txt (Txt'First + 7 .. Txt'Last));
726 -- No prefix needed for check message, severity is there already
728 elsif E_Msg.Check then
730 -- The message format is "severity: ..."
732 -- Enclose the severity with an SGR control string if requested
734 if Use_SGR_Control then
736 Msg : String renames Text.all;
737 Colon : Natural := 0;
741 for J in Msg'Range loop
742 if Msg (J) = ':' then
748 pragma Assert (Colon > 0);
750 Txt := new String'(SGR_Error
751 & Msg
(Msg
'First .. Colon
)
753 & Msg
(Colon
+ 1 .. Msg
'Last));
757 -- All other cases, add "error: " if unique error tag set
759 elsif Opt
.Unique_Error_Tag
then
760 Txt
:= new String'(SGR_Error & "error: " & SGR_Reset & Txt.all);
763 -- Set error message line length and length of message
765 if Error_Msg_Line_Length = 0 then
768 Length := Error_Msg_Line_Length;
771 Max := Integer (Length - Column + 1);
774 -- Here we have to split the message up into multiple lines
778 -- Make sure we do not have ludicrously small line
780 Max := Integer'Max (Max, 20);
782 -- If remaining text fits, output it respecting LF and we are done
784 if Len - Ptr < Max then
785 for J in Ptr .. Len loop
786 if Txt (J) = ASCII.LF then
790 Write_Char (Txt (J));
801 -- First scan forward looking for a hard end of line
803 for Scan in Ptr .. Ptr + Max - 1 loop
804 if Txt (Scan) = ASCII.LF then
811 -- Otherwise scan backwards looking for a space
813 for Scan in reverse Ptr .. Ptr + Max - 1 loop
814 if Txt (Scan) = ' ' then
821 -- If we fall through, no space, so split line arbitrarily
823 Split := Ptr + Max - 1;
828 if Start <= Split then
829 Write_Line (Txt (Start .. Split));
833 Max := Integer (Length - Column + 1);
837 ---------------------
838 -- Prescan_Message --
839 ---------------------
841 procedure Prescan_Message (Msg : String) is
845 -- Nothing to do for continuation line, unless -gnatdF is set
847 if not Debug_Flag_FF and then Msg (Msg'First) = '\
' then
850 -- Some global variables are not set for continuation messages, as they
851 -- only make sense for the initial mesage.
853 elsif Msg (Msg'First) /= '\
' then
855 -- Set initial values of globals (may be changed during scan)
857 Is_Serious_Error := True;
858 Is_Unconditional_Msg := False;
859 Is_Warning_Msg := False;
861 -- Check style message
865 and then Msg (Msg'First .. Msg'First + 6) = "(style)";
867 -- Check info message
871 and then Msg (Msg'First .. Msg'First + 5) = "info: ";
873 -- Check check message
877 and then Msg (Msg'First .. Msg'First + 7) = "medium: ")
880 and then Msg (Msg'First .. Msg'First + 5) = "high: ")
883 and then Msg (Msg'First .. Msg'First + 4) = "low: ");
886 Has_Double_Exclam := False;
887 Has_Insertion_Line := False;
889 -- Loop through message looking for relevant insertion sequences
892 while J <= Msg'Last loop
894 -- If we have a quote, don't look at following character
896 if Msg (J) = ''' then
899 -- Warning message (? or < insertion sequence)
901 elsif Msg (J) = '?
' or else Msg (J) = '<' then
902 Is_Warning_Msg := Msg (J) = '?
' or else Error_Msg_Warn;
903 Warning_Msg_Char := ' ';
906 if Is_Warning_Msg then
908 C : constant Character := Msg (J - 1);
910 if J <= Msg'Last then
912 Warning_Msg_Char := '?
';
915 elsif J < Msg'Last and then Msg (J + 1) = C
916 and then (Msg (J) in 'a
' .. 'z
' or else
917 Msg (J) in 'A
' .. 'Z
' or else
918 Msg (J) = '*' or else
921 Warning_Msg_Char := Msg (J);
928 -- Bomb if untagged warning message. This code can be uncommented
929 -- for debugging when looking for untagged warning messages.
931 -- if Is_Warning_Msg and then Warning_Msg_Char = ' ' then
932 -- raise Program_Error;
935 -- Unconditional message (! insertion)
937 elsif Msg (J) = '!' then
938 Is_Unconditional_Msg := True;
941 if J <= Msg'Last and then Msg (J) = '!' then
942 Has_Double_Exclam := True;
946 -- Insertion line (# insertion)
948 elsif Msg (J) = '#
' then
949 Has_Insertion_Line := True;
952 -- Non-serious error (| insertion)
954 elsif Msg (J) = '|
' then
955 Is_Serious_Error := False;
963 if Is_Info_Msg or Is_Warning_Msg or Is_Style_Msg or Is_Check_Msg then
964 Is_Serious_Error := False;
972 procedure Purge_Messages (From : Source_Ptr; To : Source_Ptr) is
975 function To_Be_Purged (E : Error_Msg_Id) return Boolean;
976 -- Returns True for a message that is to be purged. Also adjusts
977 -- error counts appropriately.
983 function To_Be_Purged (E : Error_Msg_Id) return Boolean is
986 and then Errors.Table (E).Sptr.Ptr > From
987 and then Errors.Table (E).Sptr.Ptr < To
989 if Errors.Table (E).Warn or else Errors.Table (E).Style then
990 Warnings_Detected := Warnings_Detected - 1;
993 Total_Errors_Detected := Total_Errors_Detected - 1;
995 if Errors.Table (E).Serious then
996 Serious_Errors_Detected := Serious_Errors_Detected - 1;
1007 -- Start of processing for Purge_Messages
1010 while To_Be_Purged (First_Error_Msg) loop
1011 First_Error_Msg := Errors.Table (First_Error_Msg).Next;
1014 E := First_Error_Msg;
1015 while E /= No_Error_Msg loop
1016 while To_Be_Purged (Errors.Table (E).Next) loop
1017 Errors.Table (E).Next :=
1018 Errors.Table (Errors.Table (E).Next).Next;
1021 E := Errors.Table (E).Next;
1029 function Same_Error (M1, M2 : Error_Msg_Id) return Boolean is
1030 Msg1 : constant String_Ptr := Errors.Table (M1).Text;
1031 Msg2 : constant String_Ptr := Errors.Table (M2).Text;
1033 Msg2_Len : constant Integer := Msg2'Length;
1034 Msg1_Len : constant Integer := Msg1'Length;
1040 (Msg1_Len - 10 > Msg2_Len
1042 Msg2.all = Msg1.all (1 .. Msg2_Len)
1044 Msg1 (Msg2_Len + 1 .. Msg2_Len + 10) = ", instance")
1046 (Msg2_Len - 10 > Msg1_Len
1048 Msg1.all = Msg2.all (1 .. Msg1_Len)
1050 Msg2 (Msg1_Len + 1 .. Msg1_Len + 10) = ", instance");
1057 procedure Set_Msg_Blank is
1060 and then Msg_Buffer (Msglen) /= ' '
1061 and then Msg_Buffer (Msglen) /= '('
1062 and then Msg_Buffer (Msglen) /= '-'
1063 and then not Manual_Quote_Mode
1069 -------------------------------
1070 -- Set_Msg_Blank_Conditional --
1071 -------------------------------
1073 procedure Set_Msg_Blank_Conditional is
1076 and then Msg_Buffer (Msglen) /= ' '
1077 and then Msg_Buffer (Msglen) /= '('
1078 and then Msg_Buffer (Msglen) /= '"'
1079 and then not Manual_Quote_Mode
1083 end Set_Msg_Blank_Conditional;
1089 procedure Set_Msg_Char (C : Character) is
1092 -- The check for message buffer overflow is needed to deal with cases
1093 -- where insertions get too long (in particular a child unit name can
1096 if Msglen < Max_Msg_Length then
1097 Msglen := Msglen + 1;
1098 Msg_Buffer (Msglen) := C;
1102 ---------------------------------
1103 -- Set_Msg_Insertion_File_Name --
1104 ---------------------------------
1106 procedure Set_Msg_Insertion_File_Name is
1108 if Error_Msg_File_1 = No_File then
1111 elsif Error_Msg_File_1 = Error_File_Name then
1113 Set_Msg_Str ("<error
>");
1117 Get_Name_String (Error_Msg_File_1);
1119 Set_Msg_Name_Buffer;
1123 -- The following assignments ensure that the second and third {
1124 -- insertion characters will correspond to the Error_Msg_File_2
1125 -- and Error_Msg_File_3 values.
1127 Error_Msg_File_1 := Error_Msg_File_2;
1128 Error_Msg_File_2 := Error_Msg_File_3;
1129 end Set_Msg_Insertion_File_Name;
1131 -----------------------------------
1132 -- Set_Msg_Insertion_Line_Number --
1133 -----------------------------------
1135 procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr) is
1136 Sindex_Loc : Source_File_Index;
1137 Sindex_Flag : Source_File_Index;
1138 Fname : File_Name_Type;
1142 -- Outputs "at " unless last characters in buffer are " from
". Certain
1143 -- messages read better with from than at.
1152 or else Msg_Buffer (Msglen - 5 .. Msglen) /= " from
"
1154 Set_Msg_Str ("at ");
1158 -- Start of processing for Set_Msg_Insertion_Line_Number
1163 if Loc = No_Location then
1165 Set_Msg_Str ("unknown location
");
1167 elsif Loc = System_Location then
1168 Set_Msg_Str ("in package System
");
1169 Set_Msg_Insertion_Run_Time_Name;
1171 elsif Loc = Standard_Location then
1172 Set_Msg_Str ("in package Standard
");
1174 elsif Loc = Standard_ASCII_Location then
1175 Set_Msg_Str ("in package Standard
.ASCII
");
1178 -- Add "at file
-name
:" if reference is to other than the source
1179 -- file in which the error message is placed. Note that we check
1180 -- full file names, rather than just the source indexes, to
1181 -- deal with generic instantiations from the current file.
1183 Sindex_Loc := Get_Source_File_Index (Loc);
1184 Sindex_Flag := Get_Source_File_Index (Flag);
1186 if Full_File_Name (Sindex_Loc) /= Full_File_Name (Sindex_Flag) then
1188 Fname := Reference_Name (Get_Source_File_Index (Loc));
1189 Int_File := Is_Internal_File_Name (Fname);
1190 Get_Name_String (Fname);
1191 Set_Msg_Name_Buffer;
1193 if not (Int_File and Debug_Flag_Dot_K) then
1195 Set_Msg_Int (Int (Get_Logical_Line_Number (Loc)));
1198 -- If in current file, add text "at line
"
1202 Set_Msg_Str ("line
");
1204 Set_Msg_Int (Int (Get_Logical_Line_Number (Loc)));
1207 -- Deal with the instantiation case. We may have a reference to,
1208 -- e.g. a type, that is declared within a generic template, and
1209 -- what we are really referring to is the occurrence in an instance.
1210 -- In this case, the line number of the instantiation is also of
1211 -- interest, and we add a notation:
1213 -- , instance at xxx
1215 -- where xxx is a line number output using this same routine (and
1216 -- the recursion can go further if the instantiation is itself in
1217 -- a generic template).
1219 -- The flag location passed to us in this situation is indeed the
1220 -- line number within the template, but as described in Sinput.L
1221 -- (file sinput-l.ads, section "Handling
Generic Instantiations
")
1222 -- we can retrieve the location of the instantiation itself from
1223 -- this flag location value.
1225 -- Note: this processing is suppressed if Suppress_Instance_Location
1226 -- is set True. This is used to prevent redundant annotations of the
1227 -- location of the instantiation in the case where we are placing
1228 -- the messages on the instantiation in any case.
1230 if Instantiation (Sindex_Loc) /= No_Location
1231 and then not Suppress_Instance_Location
1233 Set_Msg_Str (", instance
");
1234 Set_Msg_Insertion_Line_Number (Instantiation (Sindex_Loc), Flag);
1237 end Set_Msg_Insertion_Line_Number;
1239 ----------------------------
1240 -- Set_Msg_Insertion_Name --
1241 ----------------------------
1243 procedure Set_Msg_Insertion_Name is
1245 if Error_Msg_Name_1 = No_Name then
1248 elsif Error_Msg_Name_1 = Error_Name then
1250 Set_Msg_Str ("<error
>");
1253 Set_Msg_Blank_Conditional;
1254 Get_Unqualified_Decoded_Name_String (Error_Msg_Name_1);
1256 -- Remove %s or %b at end. These come from unit names. If the
1257 -- caller wanted the (unit) or (body), then they would have used
1258 -- the $ insertion character. Certainly no error message should
1259 -- ever have %b or %s explicitly occurring.
1262 and then Name_Buffer (Name_Len - 1) = '%'
1263 and then (Name_Buffer (Name_Len) = 'b'
1265 Name_Buffer (Name_Len) = 's')
1267 Name_Len := Name_Len - 2;
1270 -- Remove upper case letter at end, again, we should not be getting
1271 -- such names, and what we hope is that the remainder makes sense.
1273 if Name_Len > 1 and then Name_Buffer (Name_Len) in 'A' .. 'Z' then
1274 Name_Len := Name_Len - 1;
1277 -- If operator name or character literal name, just print it as is
1278 -- Also print as is if it ends in a right paren (case of x'val(nnn))
1280 if Name_Buffer (1) = '"'
1281 or else Name_Buffer (1) = '''
1282 or else Name_Buffer (Name_Len) = ')'
1284 Set_Msg_Name_Buffer;
1286 -- Else output with surrounding quotes in proper casing mode
1289 Set_Casing (Identifier_Casing (Flag_Source));
1291 Set_Msg_Name_Buffer;
1296 -- The following assignments ensure that the second and third percent
1297 -- insertion characters will correspond to the Error_Msg_Name_2 and
1298 -- Error_Msg_Name_3 as required.
1300 Error_Msg_Name_1 := Error_Msg_Name_2;
1301 Error_Msg_Name_2 := Error_Msg_Name_3;
1302 end Set_Msg_Insertion_Name;
1304 ------------------------------------
1305 -- Set_Msg_Insertion_Name_Literal --
1306 ------------------------------------
1308 procedure Set_Msg_Insertion_Name_Literal is
1310 if Error_Msg_Name_1 = No_Name then
1313 elsif Error_Msg_Name_1 = Error_Name then
1315 Set_Msg_Str ("<error>");
1319 Get_Name_String (Error_Msg_Name_1);
1321 Set_Msg_Name_Buffer;
1325 -- The following assignments ensure that the second and third % or %%
1326 -- insertion characters will correspond to the Error_Msg_Name_2 and
1327 -- Error_Msg_Name_3 values.
1329 Error_Msg_Name_1 := Error_Msg_Name_2;
1330 Error_Msg_Name_2 := Error_Msg_Name_3;
1331 end Set_Msg_Insertion_Name_Literal;
1333 -------------------------------------
1334 -- Set_Msg_Insertion_Reserved_Name --
1335 -------------------------------------
1337 procedure Set_Msg_Insertion_Reserved_Name is
1339 Set_Msg_Blank_Conditional;
1340 Get_Name_String (Error_Msg_Name_1);
1342 Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
1343 Set_Msg_Name_Buffer;
1345 end Set_Msg_Insertion_Reserved_Name;
1347 -------------------------------------
1348 -- Set_Msg_Insertion_Reserved_Word --
1349 -------------------------------------
1351 procedure Set_Msg_Insertion_Reserved_Word
1356 Set_Msg_Blank_Conditional;
1359 while J <= Text'Last and then Text (J) in 'A
' .. 'Z
' loop
1360 Add_Char_To_Name_Buffer (Text (J));
1364 -- Here is where we make the special exception for RM
1366 if Name_Len = 2 and then Name_Buffer (1 .. 2) = "RM" then
1367 Set_Msg_Name_Buffer;
1369 -- We make a similar exception for SPARK
1371 elsif Name_Len = 5 and then Name_Buffer (1 .. 5) = "SPARK" then
1372 Set_Msg_Name_Buffer;
1374 -- Neither RM nor SPARK: case appropriately and add surrounding quotes
1377 Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
1379 Set_Msg_Name_Buffer;
1382 end Set_Msg_Insertion_Reserved_Word;
1384 -------------------------------------
1385 -- Set_Msg_Insertion_Run_Time_Name --
1386 -------------------------------------
1388 procedure Set_Msg_Insertion_Run_Time_Name is
1390 if Targparm.Run_Time_Name_On_Target /= No_Name then
1391 Set_Msg_Blank_Conditional;
1393 Get_Name_String (Targparm.Run_Time_Name_On_Target);
1394 Set_Casing (Mixed_Case);
1395 Set_Msg_Str (Name_Buffer (1 .. Name_Len));
1398 end Set_Msg_Insertion_Run_Time_Name;
1400 ----------------------------
1401 -- Set_Msg_Insertion_Uint --
1402 ----------------------------
1404 procedure Set_Msg_Insertion_Uint is
1407 UI_Image (Error_Msg_Uint_1);
1409 for J in 1 .. UI_Image_Length loop
1410 Set_Msg_Char (UI_Image_Buffer (J));
1413 -- The following assignment ensures that a second caret insertion
1414 -- character will correspond to the Error_Msg_Uint_2 parameter.
1416 Error_Msg_Uint_1 := Error_Msg_Uint_2;
1417 end Set_Msg_Insertion_Uint;
1423 procedure Set_Msg_Int (Line : Int) is
1426 Set_Msg_Int (Line / 10);
1429 Set_Msg_Char (Character'Val (Character'Pos ('0') + (Line rem 10)));
1432 -------------------------
1433 -- Set_Msg_Name_Buffer --
1434 -------------------------
1436 procedure Set_Msg_Name_Buffer is
1438 Set_Msg_Str (Name_Buffer (1 .. Name_Len));
1439 end Set_Msg_Name_Buffer;
1445 procedure Set_Msg_Quote is
1447 if not Manual_Quote_Mode then
1456 procedure Set_Msg_Str (Text : String) is
1458 -- Do replacement for special x'Class aspect names
1460 if Text = "_Pre
" then
1461 Set_Msg_Str ("Pre
'Class");
1463 elsif Text = "_Post
" then
1464 Set_Msg_Str ("Post
'Class");
1466 elsif Text = "_Type_Invariant
" then
1467 Set_Msg_Str ("Type_Invariant
'Class");
1469 elsif Text = "_pre
" then
1470 Set_Msg_Str ("pre
'class");
1472 elsif Text = "_post
" then
1473 Set_Msg_Str ("post
'class");
1475 elsif Text = "_type_invariant
" then
1476 Set_Msg_Str ("type_invariant
'class");
1478 elsif Text = "_PRE
" then
1479 Set_Msg_Str ("PRE
'CLASS");
1481 elsif Text = "_POST
" then
1482 Set_Msg_Str ("POST
'CLASS");
1484 elsif Text = "_TYPE_INVARIANT
" then
1485 Set_Msg_Str ("TYPE_INVARIANT
'CLASS");
1487 -- Normal case with no replacement
1490 for J in Text'Range loop
1491 Set_Msg_Char (Text (J));
1496 ------------------------------
1497 -- Set_Next_Non_Deleted_Msg --
1498 ------------------------------
1500 procedure Set_Next_Non_Deleted_Msg (E : in out Error_Msg_Id) is
1502 if E = No_Error_Msg then
1507 E := Errors.Table (E).Next;
1508 exit when E = No_Error_Msg or else not Errors.Table (E).Deleted;
1511 end Set_Next_Non_Deleted_Msg;
1513 ------------------------------
1514 -- Set_Specific_Warning_Off --
1515 ------------------------------
1517 procedure Set_Specific_Warning_Off
1522 Used : Boolean := False)
1525 Specific_Warnings.Append
1527 Msg => new String'(Msg),
1528 Stop => Source_Last (Get_Source_File_Index (Loc)),
1533 end Set_Specific_Warning_Off;
1535 -----------------------------
1536 -- Set_Specific_Warning_On --
1537 -----------------------------
1539 procedure Set_Specific_Warning_On
1545 for J in 1 .. Specific_Warnings.Last loop
1547 SWE : Specific_Warning_Entry renames Specific_Warnings.Table (J);
1550 if Msg = SWE.Msg.all
1551 and then Loc > SWE.Start
1553 and then Get_Source_File_Index (SWE.Start) =
1554 Get_Source_File_Index (Loc)
1560 -- If a config pragma is specifically cancelled, consider
1561 -- that it is no longer active as a configuration pragma.
1563 SWE.Config := False;
1570 end Set_Specific_Warning_On;
1572 ---------------------------
1573 -- Set_Warnings_Mode_Off --
1574 ---------------------------
1576 procedure Set_Warnings_Mode_Off (Loc : Source_Ptr; Reason : String_Id) is
1578 -- Don't bother with entries from instantiation copies, since we will
1579 -- already have a copy in the template, which is what matters.
1581 if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
1585 -- If all warnings are suppressed by command line switch, this can
1586 -- be ignored, unless we are in GNATprove_Mode which requires pragma
1587 -- Warnings to be stored for the formal verification backend.
1589 if Warning_Mode = Suppress
1590 and then not GNATprove_Mode
1595 -- If last entry in table already covers us, this is a redundant pragma
1596 -- Warnings (Off) and can be ignored.
1598 if Warnings.Last >= Warnings.First
1599 and then Warnings.Table (Warnings.Last).Start <= Loc
1600 and then Loc <= Warnings.Table (Warnings.Last).Stop
1605 -- If none of those special conditions holds, establish a new entry,
1606 -- extending from the location of the pragma to the end of the current
1607 -- source file. This ending point will be adjusted by a subsequent
1608 -- corresponding pragma Warnings (On).
1612 Stop => Source_Last (Get_Source_File_Index (Loc)),
1614 end Set_Warnings_Mode_Off;
1616 --------------------------
1617 -- Set_Warnings_Mode_On --
1618 --------------------------
1620 procedure Set_Warnings_Mode_On (Loc : Source_Ptr) is
1622 -- Don't bother with entries from instantiation copies, since we will
1623 -- already have a copy in the template, which is what matters.
1625 if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
1629 -- If all warnings are suppressed by command line switch, this can
1630 -- be ignored, unless we are in GNATprove_Mode which requires pragma
1631 -- Warnings to be stored for the formal verification backend.
1633 if Warning_Mode = Suppress
1634 and then not GNATprove_Mode
1639 -- If the last entry in the warnings table covers this pragma, then
1640 -- we adjust the end point appropriately.
1642 if Warnings.Last >= Warnings.First
1643 and then Warnings.Table (Warnings.Last).Start <= Loc
1644 and then Loc <= Warnings.Table (Warnings.Last).Stop
1646 Warnings.Table (Warnings.Last).Stop := Loc;
1648 end Set_Warnings_Mode_On;
1654 function Sloc_In_Range (Loc, Start, Stop : Source_Ptr) return Boolean is
1655 Cur_Loc : Source_Ptr := Loc;
1658 while Cur_Loc /= No_Location loop
1659 if Start <= Cur_Loc and then Cur_Loc <= Stop then
1663 Cur_Loc := Instantiation_Location (Cur_Loc);
1669 --------------------------------
1670 -- Validate_Specific_Warnings --
1671 --------------------------------
1673 procedure Validate_Specific_Warnings (Eproc : Error_Msg_Proc) is
1675 if not Warn_On_Warnings_Off then
1679 for J in Specific_Warnings.First .. Specific_Warnings.Last loop
1681 SWE : Specific_Warning_Entry renames Specific_Warnings.Table (J);
1684 if not SWE.Config then
1686 -- Warn for unmatched Warnings (Off, ...)
1690 ("?W?
pragma Warnings Off
with no matching Warnings On
",
1693 -- Warn for ineffective Warnings (Off, ..)
1697 -- Do not issue this warning for -Wxxx messages since the
1698 -- back-end doesn't report the information. Note that there
1699 -- is always an asterisk at the start of every message.
1702 (SWE.Msg'Length > 3 and then SWE.Msg (2 .. 3) = "-W
")
1705 ("?W?no warning suppressed by this
pragma", SWE.Start);
1710 end Validate_Specific_Warnings;
1712 -------------------------------------
1713 -- Warning_Specifically_Suppressed --
1714 -------------------------------------
1716 function Warning_Specifically_Suppressed
1719 Tag : String := "") return String_Id
1722 -- Loop through specific warning suppression entries
1724 for J in Specific_Warnings.First .. Specific_Warnings.Last loop
1726 SWE : Specific_Warning_Entry renames Specific_Warnings.Table (J);
1729 -- Pragma applies if it is a configuration pragma, or if the
1730 -- location is in range of a specific non-configuration pragma.
1733 or else Sloc_In_Range (Loc, SWE.Start, SWE.Stop)
1735 if Matches (Msg.all, SWE.Msg.all)
1736 or else Matches (Tag, SWE.Msg.all)
1746 end Warning_Specifically_Suppressed;
1748 ------------------------------
1749 -- Warning_Treated_As_Error --
1750 ------------------------------
1752 function Warning_Treated_As_Error (Msg : String) return Boolean is
1754 for J in 1 .. Warnings_As_Errors_Count loop
1755 if Matches (Msg, Warnings_As_Errors (J).all) then
1761 end Warning_Treated_As_Error;
1763 -------------------------
1764 -- Warnings_Suppressed --
1765 -------------------------
1767 function Warnings_Suppressed (Loc : Source_Ptr) return String_Id is
1769 -- Loop through table of ON/OFF warnings
1771 for J in Warnings.First .. Warnings.Last loop
1772 if Sloc_In_Range (Loc, Warnings.Table (J).Start,
1773 Warnings.Table (J).Stop)
1775 return Warnings.Table (J).Reason;
1779 if Warning_Mode = Suppress then
1780 return Null_String_Id;
1784 end Warnings_Suppressed;