2004-05-10 Doug Rupp <rupp@gnat.com> * 5qsystem.ads: Remove Short_Address subtype declaration. Moved to system.aux_dec. * s-auxdec.ads: Add Short_Address subtype (moved here from System). * Makefile.in: [VMS]: Add translation for 5qauxdec.ads. * init.c: [VMS] Macroize LIB$ calls for IA64 and Alpha. Fixes undefined symbols in IA64 gnatlib. * 5vinmaop.adb: Reference s-auxdec for Short_Address. * 5xsystem.ads, 5vsystem.ads: Back out last change (addition of subtype Short_Address). This will be moved to system.auxdec. 2004-05-10 Thomas Quinot <quinot@act-europe.fr> * sem_util.adb: Replace test for presence of a node that is always present with a call to Discard_Node. * sem_ch10.adb (Analyze_Compilation_Unit): Remove superfluous call to Analyze on the library unit node after generation of distribution stub constructs. The call was a no-op because Unit_Node has already been Analyzed, and the tree fragments for the distribution stubs are analyzed as they are inserted in Exp_Dist. Update comment regarding to distribution stubs to reflect that we do not generate stub in separate files anymore. * einfo.ads: Clarify the fact that a tagged private type has the E_Record_Type_With_Private Ekind. * erroutc.adb: Minor reformatting * erroutc.ads (Max_Msg_Length): Increase to cover possible larger values if line length is increased using -gnatyM (noticed during code reading). * eval_fat.adb: Minor reformatting Put spaces around exponentiation operator 2004-05-10 Ed Schonberg <schonberg@gnat.com> PR ada/15005 * sem_util.adb (Is_Dependent_Component_Of_Mutable_Object): If prefix has been rewritten as an explicit dereference, retrieve type of original node to check for possibly unconstrained record type. 2004-05-10 Ed Schonberg <schonberg@gnat.com> * exp_ch7.adb (Check_Visibly_Controlled): If given operation is not overriding, use the operation of the parent unconditionally. * sem_ch4.adb (Remove_Address_Interpretations): Remove address operation when either operand is a literal, to avoid further ambiguities. * sem_ch6.adb (New_Overloaded_Entity): If new entity is inherited and overridden by a previous explicit declaration, mark the previous entity as overriding. * sem_disp.adb (Check_Dispatching_Operation): New predicate Is_Visibly_Controlled, to determine whether a declaration of a primitive control operation for a derived type overrides an inherited one. Add warning if the explicit declaration does not override. 2004-05-10 Vincent Celier <celier@gnat.com> * gnatls.adb (Gnatls): Initialize Snames, to avoid assertion error in some cases when the sources are no longer present. * make.adb (Collect_Arguments): Fail if an external source, not part of any project need to be compiled, when switch -x has not been specified. * makeusg.adb: Document new switch -x * opt.ads (External_Unit_Compilation_Allowed): New Boolean flag, defaulted to False. * switch-m.adb (Scan_Make_Switches): New switch -x * vms_data.ads: Add VMS qualifier /NON_PROJECT_UNIT_COMPILATION for gnatmake switch -x. * gnat_ugn.texi: Document new gnatmake switch -x 2004-05-10 Eric Botcazou <ebotcazou@act-europe.fr> * misc.c (gnat_init_options): Set flag_zero_initialized_in_bss to 0. * utils.c (create_var_decl): Do not modify the DECL_COMMON flag. (process_attributes): Likewise. 2004-05-10 Joel Brobecker <brobecker@gnat.com> * s-inmaop.ads: Fix spelling mistake in one of the comments. 2004-05-10 Robert Dewar <dewar@gnat.com> * gnat_ugn.texi: Document that for config pragma files, the maximum line length is always 32767. * gnat_rm.texi: For pragma Eliminate, note that concatenation of string literals is now allowed. * gnat-style.texi: Remove statement about splitting long lines before an operator rather than after, since we do not follow this rule at all. Clarify rule (really lack of rule) for spaces around exponentiation * sem_elim.adb: Allow concatenation of string literals as well as a single string literal for pragma arguments. * sem_prag.ads, sem_prag.adb: (Is_Config_Static_String): New function * a-textio.adb (Terminate_Line): Do not add line feed if nothing written for append case. * frontend.adb: Changes to avoid checking max line length in config pragma files. * g-os_lib.ads: Minor reformatting * mlib-utl.adb: Do not define Max_Line_Length locally (definition was wrong in any case. Instead use standard value. Noticed during code reading. * opt.ads (Max_Line_Length): New field, used to implement removal of limitation on length of lines when scanning config pragma files. * osint.ads, prj-dect.adb, prj-strt.adb, prj-tree.adb, makeutl.ads, makeutl.adb: Minor reformatting * scn.adb: Do not check line length while scanning config pragma files Do not check line length while scanning out license information * scng.adb: Changes to avoid line length checks while parsing config pragma files. 2004-05-10 GNAT Script <nobody@gnat.com> * Make-lang.in: Makefile automatically updated From-SVN: r81671
1016 lines
30 KiB
Ada
1016 lines
30 KiB
Ada
------------------------------------------------------------------------------
|
|
-- --
|
|
-- GNAT COMPILER COMPONENTS --
|
|
-- --
|
|
-- E R R O U T C --
|
|
-- --
|
|
-- B o d y --
|
|
-- --
|
|
-- Copyright (C) 1992-2004 Free Software Foundation, Inc. --
|
|
-- --
|
|
-- GNAT is free software; you can redistribute it and/or modify it under --
|
|
-- terms of the GNU General Public License as published by the Free Soft- --
|
|
-- ware Foundation; either version 2, or (at your option) any later ver- --
|
|
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
|
|
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
|
|
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
|
|
-- for more details. You should have received a copy of the GNU General --
|
|
-- Public License distributed with GNAT; see file COPYING. If not, write --
|
|
-- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
|
|
-- MA 02111-1307, USA. --
|
|
-- --
|
|
-- GNAT was originally developed by the GNAT team at New York University. --
|
|
-- Extensive contributions were provided by Ada Core Technologies Inc. --
|
|
-- --
|
|
------------------------------------------------------------------------------
|
|
|
|
-- Warning! Error messages can be generated during Gigi processing by direct
|
|
-- calls to error message routines, so it is essential that the processing
|
|
-- in this body be consistent with the requirements for the Gigi processing
|
|
-- environment, and that in particular, no disallowed table expansion is
|
|
-- allowed to occur.
|
|
|
|
with Casing; use Casing;
|
|
with Debug; use Debug;
|
|
with Err_Vars; use Err_Vars;
|
|
with Namet; use Namet;
|
|
with Opt; use Opt;
|
|
with Output; use Output;
|
|
with Sinput; use Sinput;
|
|
with Snames; use Snames;
|
|
with Targparm; use Targparm;
|
|
with Table;
|
|
with Types; use Types;
|
|
with Uintp; use Uintp;
|
|
|
|
package body Erroutc is
|
|
|
|
-----------------------
|
|
-- Local Subprograms --
|
|
-----------------------
|
|
|
|
---------------
|
|
-- Add_Class --
|
|
---------------
|
|
|
|
procedure Add_Class is
|
|
begin
|
|
if Class_Flag then
|
|
Class_Flag := False;
|
|
Set_Msg_Char (''');
|
|
Get_Name_String (Name_Class);
|
|
Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
|
|
Set_Msg_Name_Buffer;
|
|
end if;
|
|
end Add_Class;
|
|
|
|
----------------------
|
|
-- Buffer_Ends_With --
|
|
----------------------
|
|
|
|
function Buffer_Ends_With (S : String) return Boolean is
|
|
Len : constant Natural := S'Length;
|
|
begin
|
|
return
|
|
Msglen > Len
|
|
and then Msg_Buffer (Msglen - Len) = ' '
|
|
and then Msg_Buffer (Msglen - Len + 1 .. Msglen) = S;
|
|
end Buffer_Ends_With;
|
|
|
|
-------------------
|
|
-- Buffer_Remove --
|
|
-------------------
|
|
|
|
procedure Buffer_Remove (S : String) is
|
|
begin
|
|
if Buffer_Ends_With (S) then
|
|
Msglen := Msglen - S'Length;
|
|
end if;
|
|
end Buffer_Remove;
|
|
|
|
-----------------------------
|
|
-- Check_Duplicate_Message --
|
|
-----------------------------
|
|
|
|
procedure Check_Duplicate_Message (M1, M2 : Error_Msg_Id) is
|
|
L1, L2 : Error_Msg_Id;
|
|
N1, N2 : Error_Msg_Id;
|
|
|
|
procedure Delete_Msg (Delete, Keep : Error_Msg_Id);
|
|
-- Called to delete message Delete, keeping message Keep. Marks
|
|
-- all messages of Delete with deleted flag set to True, and also
|
|
-- makes sure that for the error messages that are retained the
|
|
-- preferred message is the one retained (we prefer the shorter
|
|
-- one in the case where one has an Instance tag). Note that we
|
|
-- always know that Keep has at least as many continuations as
|
|
-- Delete (since we always delete the shorter sequence).
|
|
|
|
----------------
|
|
-- Delete_Msg --
|
|
----------------
|
|
|
|
procedure Delete_Msg (Delete, Keep : Error_Msg_Id) is
|
|
D, K : Error_Msg_Id;
|
|
|
|
begin
|
|
D := Delete;
|
|
K := Keep;
|
|
|
|
loop
|
|
Errors.Table (D).Deleted := True;
|
|
|
|
-- Adjust error message count
|
|
|
|
if Errors.Table (D).Warn or Errors.Table (D).Style then
|
|
Warnings_Detected := Warnings_Detected - 1;
|
|
else
|
|
Total_Errors_Detected := Total_Errors_Detected - 1;
|
|
|
|
if Errors.Table (D).Serious then
|
|
Serious_Errors_Detected := Serious_Errors_Detected - 1;
|
|
end if;
|
|
end if;
|
|
|
|
-- Substitute shorter of the two error messages
|
|
|
|
if Errors.Table (K).Text'Length > Errors.Table (D).Text'Length then
|
|
Errors.Table (K).Text := Errors.Table (D).Text;
|
|
end if;
|
|
|
|
D := Errors.Table (D).Next;
|
|
K := Errors.Table (K).Next;
|
|
|
|
if D = No_Error_Msg or else not Errors.Table (D).Msg_Cont then
|
|
return;
|
|
end if;
|
|
end loop;
|
|
end Delete_Msg;
|
|
|
|
-- Start of processing for Check_Duplicate_Message
|
|
|
|
begin
|
|
-- Both messages must be non-continuation messages and not deleted
|
|
|
|
if Errors.Table (M1).Msg_Cont
|
|
or else Errors.Table (M2).Msg_Cont
|
|
or else Errors.Table (M1).Deleted
|
|
or else Errors.Table (M2).Deleted
|
|
then
|
|
return;
|
|
end if;
|
|
|
|
-- Definitely not equal if message text does not match
|
|
|
|
if not Same_Error (M1, M2) then
|
|
return;
|
|
end if;
|
|
|
|
-- Same text. See if all continuations are also identical
|
|
|
|
L1 := M1;
|
|
L2 := M2;
|
|
|
|
loop
|
|
N1 := Errors.Table (L1).Next;
|
|
N2 := Errors.Table (L2).Next;
|
|
|
|
-- If M1 continuations have run out, we delete M1, either the
|
|
-- messages have the same number of continuations, or M2 has
|
|
-- more and we prefer the one with more anyway.
|
|
|
|
if N1 = No_Error_Msg or else not Errors.Table (N1).Msg_Cont then
|
|
Delete_Msg (M1, M2);
|
|
return;
|
|
|
|
-- If M2 continuatins have run out, we delete M2
|
|
|
|
elsif N2 = No_Error_Msg or else not Errors.Table (N2).Msg_Cont then
|
|
Delete_Msg (M2, M1);
|
|
return;
|
|
|
|
-- Otherwise see if continuations are the same, if not, keep both
|
|
-- sequences, a curious case, but better to keep everything!
|
|
|
|
elsif not Same_Error (N1, N2) then
|
|
return;
|
|
|
|
-- If continuations are the same, continue scan
|
|
|
|
else
|
|
L1 := N1;
|
|
L2 := N2;
|
|
end if;
|
|
end loop;
|
|
end Check_Duplicate_Message;
|
|
|
|
------------------------
|
|
-- Compilation_Errors --
|
|
------------------------
|
|
|
|
function Compilation_Errors return Boolean is
|
|
begin
|
|
return Total_Errors_Detected /= 0
|
|
or else (Warnings_Detected /= 0
|
|
and then Warning_Mode = Treat_As_Error);
|
|
end Compilation_Errors;
|
|
|
|
------------------
|
|
-- Debug_Output --
|
|
------------------
|
|
|
|
procedure Debug_Output (N : Node_Id) is
|
|
begin
|
|
if Debug_Flag_1 then
|
|
Write_Str ("*** following error message posted on node id = #");
|
|
Write_Int (Int (N));
|
|
Write_Str (" ***");
|
|
Write_Eol;
|
|
end if;
|
|
end Debug_Output;
|
|
|
|
----------
|
|
-- dmsg --
|
|
----------
|
|
|
|
procedure dmsg (Id : Error_Msg_Id) is
|
|
E : Error_Msg_Object renames Errors.Table (Id);
|
|
|
|
begin
|
|
w ("Dumping error message, Id = ", Int (Id));
|
|
w (" Text = ", E.Text.all);
|
|
w (" Next = ", Int (E.Next));
|
|
w (" Sfile = ", Int (E.Sfile));
|
|
|
|
Write_Str
|
|
(" Sptr = ");
|
|
Write_Location (E.Sptr);
|
|
Write_Eol;
|
|
|
|
Write_Str
|
|
(" Optr = ");
|
|
Write_Location (E.Optr);
|
|
Write_Eol;
|
|
|
|
w (" Line = ", Int (E.Line));
|
|
w (" Col = ", Int (E.Col));
|
|
w (" Warn = ", E.Warn);
|
|
w (" Style = ", E.Style);
|
|
w (" Serious = ", E.Serious);
|
|
w (" Uncond = ", E.Uncond);
|
|
w (" Msg_Cont = ", E.Msg_Cont);
|
|
w (" Deleted = ", E.Deleted);
|
|
|
|
Write_Eol;
|
|
end dmsg;
|
|
|
|
------------------
|
|
-- Get_Location --
|
|
------------------
|
|
|
|
function Get_Location (E : Error_Msg_Id) return Source_Ptr is
|
|
begin
|
|
return Errors.Table (E).Sptr;
|
|
end Get_Location;
|
|
|
|
----------------
|
|
-- Get_Msg_Id --
|
|
----------------
|
|
|
|
function Get_Msg_Id return Error_Msg_Id is
|
|
begin
|
|
return Cur_Msg;
|
|
end Get_Msg_Id;
|
|
|
|
-----------------------
|
|
-- Output_Error_Msgs --
|
|
-----------------------
|
|
|
|
procedure Output_Error_Msgs (E : in out Error_Msg_Id) is
|
|
P : Source_Ptr;
|
|
T : Error_Msg_Id;
|
|
S : Error_Msg_Id;
|
|
|
|
Flag_Num : Pos;
|
|
Mult_Flags : Boolean := False;
|
|
|
|
begin
|
|
S := E;
|
|
|
|
-- Skip deleted messages at start
|
|
|
|
if Errors.Table (S).Deleted then
|
|
Set_Next_Non_Deleted_Msg (S);
|
|
end if;
|
|
|
|
-- Figure out if we will place more than one error flag on this line
|
|
|
|
T := S;
|
|
while T /= No_Error_Msg
|
|
and then Errors.Table (T).Line = Errors.Table (E).Line
|
|
and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
|
|
loop
|
|
if Errors.Table (T).Sptr > Errors.Table (E).Sptr then
|
|
Mult_Flags := True;
|
|
end if;
|
|
|
|
Set_Next_Non_Deleted_Msg (T);
|
|
end loop;
|
|
|
|
-- Output the error flags. The circuit here makes sure that the tab
|
|
-- characters in the original line are properly accounted for. The
|
|
-- eight blanks at the start are to match the line number.
|
|
|
|
if not Debug_Flag_2 then
|
|
Write_Str (" ");
|
|
P := Line_Start (Errors.Table (E).Sptr);
|
|
Flag_Num := 1;
|
|
|
|
-- Loop through error messages for this line to place flags
|
|
|
|
T := S;
|
|
while T /= No_Error_Msg
|
|
and then Errors.Table (T).Line = Errors.Table (E).Line
|
|
and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
|
|
loop
|
|
-- Loop to output blanks till current flag position
|
|
|
|
while P < Errors.Table (T).Sptr loop
|
|
if Source_Text (Errors.Table (T).Sfile) (P) = ASCII.HT then
|
|
Write_Char (ASCII.HT);
|
|
else
|
|
Write_Char (' ');
|
|
end if;
|
|
|
|
P := P + 1;
|
|
end loop;
|
|
|
|
-- Output flag (unless already output, this happens if more
|
|
-- than one error message occurs at the same flag position).
|
|
|
|
if P = Errors.Table (T).Sptr then
|
|
if (Flag_Num = 1 and then not Mult_Flags)
|
|
or else Flag_Num > 9
|
|
then
|
|
Write_Char ('|');
|
|
else
|
|
Write_Char (Character'Val (Character'Pos ('0') + Flag_Num));
|
|
end if;
|
|
|
|
P := P + 1;
|
|
end if;
|
|
|
|
Set_Next_Non_Deleted_Msg (T);
|
|
Flag_Num := Flag_Num + 1;
|
|
end loop;
|
|
|
|
Write_Eol;
|
|
end if;
|
|
|
|
-- Now output the error messages
|
|
|
|
T := S;
|
|
while T /= No_Error_Msg
|
|
and then Errors.Table (T).Line = Errors.Table (E).Line
|
|
and then Errors.Table (T).Sfile = Errors.Table (E).Sfile
|
|
|
|
loop
|
|
Write_Str (" >>> ");
|
|
Output_Msg_Text (T);
|
|
|
|
if Debug_Flag_2 then
|
|
while Column < 74 loop
|
|
Write_Char (' ');
|
|
end loop;
|
|
|
|
Write_Str (" <<<");
|
|
end if;
|
|
|
|
Write_Eol;
|
|
Set_Next_Non_Deleted_Msg (T);
|
|
end loop;
|
|
|
|
E := T;
|
|
end Output_Error_Msgs;
|
|
|
|
------------------------
|
|
-- Output_Line_Number --
|
|
------------------------
|
|
|
|
procedure Output_Line_Number (L : Logical_Line_Number) is
|
|
D : Int; -- next digit
|
|
C : Character; -- next character
|
|
Z : Boolean; -- flag for zero suppress
|
|
N, M : Int; -- temporaries
|
|
|
|
begin
|
|
if L = No_Line_Number then
|
|
Write_Str (" ");
|
|
|
|
else
|
|
Z := False;
|
|
N := Int (L);
|
|
|
|
M := 100_000;
|
|
while M /= 0 loop
|
|
D := Int (N / M);
|
|
N := N rem M;
|
|
M := M / 10;
|
|
|
|
if D = 0 then
|
|
if Z then
|
|
C := '0';
|
|
else
|
|
C := ' ';
|
|
end if;
|
|
else
|
|
Z := True;
|
|
C := Character'Val (D + 48);
|
|
end if;
|
|
|
|
Write_Char (C);
|
|
end loop;
|
|
|
|
Write_Str (". ");
|
|
end if;
|
|
end Output_Line_Number;
|
|
|
|
---------------------
|
|
-- Output_Msg_Text --
|
|
---------------------
|
|
|
|
procedure Output_Msg_Text (E : Error_Msg_Id) is
|
|
begin
|
|
if Errors.Table (E).Warn then
|
|
Write_Str ("warning: ");
|
|
|
|
elsif Errors.Table (E).Style then
|
|
null;
|
|
|
|
elsif Opt.Unique_Error_Tag then
|
|
Write_Str ("error: ");
|
|
end if;
|
|
|
|
Write_Str (Errors.Table (E).Text.all);
|
|
end Output_Msg_Text;
|
|
|
|
--------------------
|
|
-- Purge_Messages --
|
|
--------------------
|
|
|
|
procedure Purge_Messages (From : Source_Ptr; To : Source_Ptr) is
|
|
E : Error_Msg_Id;
|
|
|
|
function To_Be_Purged (E : Error_Msg_Id) return Boolean;
|
|
-- Returns True for a message that is to be purged. Also adjusts
|
|
-- error counts appropriately.
|
|
|
|
------------------
|
|
-- To_Be_Purged --
|
|
------------------
|
|
|
|
function To_Be_Purged (E : Error_Msg_Id) return Boolean is
|
|
begin
|
|
if E /= No_Error_Msg
|
|
and then Errors.Table (E).Sptr > From
|
|
and then Errors.Table (E).Sptr < To
|
|
then
|
|
if Errors.Table (E).Warn or Errors.Table (E).Style then
|
|
Warnings_Detected := Warnings_Detected - 1;
|
|
else
|
|
Total_Errors_Detected := Total_Errors_Detected - 1;
|
|
|
|
if Errors.Table (E).Serious then
|
|
Serious_Errors_Detected := Serious_Errors_Detected - 1;
|
|
end if;
|
|
end if;
|
|
|
|
return True;
|
|
|
|
else
|
|
return False;
|
|
end if;
|
|
end To_Be_Purged;
|
|
|
|
-- Start of processing for Purge_Messages
|
|
|
|
begin
|
|
while To_Be_Purged (First_Error_Msg) loop
|
|
First_Error_Msg := Errors.Table (First_Error_Msg).Next;
|
|
end loop;
|
|
|
|
E := First_Error_Msg;
|
|
while E /= No_Error_Msg loop
|
|
while To_Be_Purged (Errors.Table (E).Next) loop
|
|
Errors.Table (E).Next :=
|
|
Errors.Table (Errors.Table (E).Next).Next;
|
|
end loop;
|
|
|
|
E := Errors.Table (E).Next;
|
|
end loop;
|
|
end Purge_Messages;
|
|
|
|
----------------
|
|
-- Same_Error --
|
|
----------------
|
|
|
|
function Same_Error (M1, M2 : Error_Msg_Id) return Boolean is
|
|
Msg1 : constant String_Ptr := Errors.Table (M1).Text;
|
|
Msg2 : constant String_Ptr := Errors.Table (M2).Text;
|
|
|
|
Msg2_Len : constant Integer := Msg2'Length;
|
|
Msg1_Len : constant Integer := Msg1'Length;
|
|
|
|
begin
|
|
return
|
|
Msg1.all = Msg2.all
|
|
or else
|
|
(Msg1_Len - 10 > Msg2_Len
|
|
and then
|
|
Msg2.all = Msg1.all (1 .. Msg2_Len)
|
|
and then
|
|
Msg1 (Msg2_Len + 1 .. Msg2_Len + 10) = ", instance")
|
|
or else
|
|
(Msg2_Len - 10 > Msg1_Len
|
|
and then
|
|
Msg1.all = Msg2.all (1 .. Msg1_Len)
|
|
and then
|
|
Msg2 (Msg1_Len + 1 .. Msg1_Len + 10) = ", instance");
|
|
end Same_Error;
|
|
|
|
-------------------
|
|
-- Set_Msg_Blank --
|
|
-------------------
|
|
|
|
procedure Set_Msg_Blank is
|
|
begin
|
|
if Msglen > 0
|
|
and then Msg_Buffer (Msglen) /= ' '
|
|
and then Msg_Buffer (Msglen) /= '('
|
|
and then not Manual_Quote_Mode
|
|
then
|
|
Set_Msg_Char (' ');
|
|
end if;
|
|
end Set_Msg_Blank;
|
|
|
|
-------------------------------
|
|
-- Set_Msg_Blank_Conditional --
|
|
-------------------------------
|
|
|
|
procedure Set_Msg_Blank_Conditional is
|
|
begin
|
|
if Msglen > 0
|
|
and then Msg_Buffer (Msglen) /= ' '
|
|
and then Msg_Buffer (Msglen) /= '('
|
|
and then Msg_Buffer (Msglen) /= '"'
|
|
and then not Manual_Quote_Mode
|
|
then
|
|
Set_Msg_Char (' ');
|
|
end if;
|
|
end Set_Msg_Blank_Conditional;
|
|
|
|
------------------
|
|
-- Set_Msg_Char --
|
|
------------------
|
|
|
|
procedure Set_Msg_Char (C : Character) is
|
|
begin
|
|
|
|
-- The check for message buffer overflow is needed to deal with cases
|
|
-- where insertions get too long (in particular a child unit name can
|
|
-- be very long).
|
|
|
|
if Msglen < Max_Msg_Length then
|
|
Msglen := Msglen + 1;
|
|
Msg_Buffer (Msglen) := C;
|
|
end if;
|
|
end Set_Msg_Char;
|
|
|
|
---------------------------------
|
|
-- Set_Msg_Insertion_File_Name --
|
|
---------------------------------
|
|
|
|
procedure Set_Msg_Insertion_File_Name is
|
|
begin
|
|
if Error_Msg_Name_1 = No_Name then
|
|
null;
|
|
|
|
elsif Error_Msg_Name_1 = Error_Name then
|
|
Set_Msg_Blank;
|
|
Set_Msg_Str ("<error>");
|
|
|
|
else
|
|
Set_Msg_Blank;
|
|
Get_Name_String (Error_Msg_Name_1);
|
|
Set_Msg_Quote;
|
|
Set_Msg_Name_Buffer;
|
|
Set_Msg_Quote;
|
|
end if;
|
|
|
|
-- The following assignments ensure that the second and third percent
|
|
-- insertion characters will correspond to the Error_Msg_Name_2 and
|
|
-- Error_Msg_Name_3 as required.
|
|
|
|
Error_Msg_Name_1 := Error_Msg_Name_2;
|
|
Error_Msg_Name_2 := Error_Msg_Name_3;
|
|
end Set_Msg_Insertion_File_Name;
|
|
|
|
-----------------------------------
|
|
-- Set_Msg_Insertion_Line_Number --
|
|
-----------------------------------
|
|
|
|
procedure Set_Msg_Insertion_Line_Number (Loc, Flag : Source_Ptr) is
|
|
Sindex_Loc : Source_File_Index;
|
|
Sindex_Flag : Source_File_Index;
|
|
|
|
begin
|
|
Set_Msg_Blank;
|
|
|
|
if Loc = No_Location then
|
|
Set_Msg_Str ("at unknown location");
|
|
|
|
elsif Loc = System_Location then
|
|
Set_Msg_Str ("in package System");
|
|
Set_Msg_Insertion_Run_Time_Name;
|
|
|
|
elsif Loc = Standard_Location then
|
|
Set_Msg_Str ("in package Standard");
|
|
|
|
elsif Loc = Standard_ASCII_Location then
|
|
Set_Msg_Str ("in package Standard.ASCII");
|
|
|
|
else
|
|
-- Add "at file-name:" if reference is to other than the source
|
|
-- file in which the error message is placed. Note that we check
|
|
-- full file names, rather than just the source indexes, to
|
|
-- deal with generic instantiations from the current file.
|
|
|
|
Sindex_Loc := Get_Source_File_Index (Loc);
|
|
Sindex_Flag := Get_Source_File_Index (Flag);
|
|
|
|
if Full_File_Name (Sindex_Loc) /= Full_File_Name (Sindex_Flag) then
|
|
Set_Msg_Str ("at ");
|
|
Get_Name_String
|
|
(Reference_Name (Get_Source_File_Index (Loc)));
|
|
Set_Msg_Name_Buffer;
|
|
Set_Msg_Char (':');
|
|
|
|
-- If in current file, add text "at line "
|
|
|
|
else
|
|
Set_Msg_Str ("at line ");
|
|
end if;
|
|
|
|
-- Output line number for reference
|
|
|
|
Set_Msg_Int (Int (Get_Logical_Line_Number (Loc)));
|
|
|
|
-- Deal with the instantiation case. We may have a reference to,
|
|
-- e.g. a type, that is declared within a generic template, and
|
|
-- what we are really referring to is the occurrence in an instance.
|
|
-- In this case, the line number of the instantiation is also of
|
|
-- interest, and we add a notation:
|
|
|
|
-- , instance at xxx
|
|
|
|
-- where xxx is a line number output using this same routine (and
|
|
-- the recursion can go further if the instantiation is itself in
|
|
-- a generic template).
|
|
|
|
-- The flag location passed to us in this situation is indeed the
|
|
-- line number within the template, but as described in Sinput.L
|
|
-- (file sinput-l.ads, section "Handling Generic Instantiations")
|
|
-- we can retrieve the location of the instantiation itself from
|
|
-- this flag location value.
|
|
|
|
-- Note: this processing is suppressed if Suppress_Instance_Location
|
|
-- is set True. This is used to prevent redundant annotations of the
|
|
-- location of the instantiation in the case where we are placing
|
|
-- the messages on the instantiation in any case.
|
|
|
|
if Instantiation (Sindex_Loc) /= No_Location
|
|
and then not Suppress_Instance_Location
|
|
then
|
|
Set_Msg_Str (", instance ");
|
|
Set_Msg_Insertion_Line_Number (Instantiation (Sindex_Loc), Flag);
|
|
end if;
|
|
end if;
|
|
end Set_Msg_Insertion_Line_Number;
|
|
|
|
----------------------------
|
|
-- Set_Msg_Insertion_Name --
|
|
----------------------------
|
|
|
|
procedure Set_Msg_Insertion_Name is
|
|
begin
|
|
if Error_Msg_Name_1 = No_Name then
|
|
null;
|
|
|
|
elsif Error_Msg_Name_1 = Error_Name then
|
|
Set_Msg_Blank;
|
|
Set_Msg_Str ("<error>");
|
|
|
|
else
|
|
Set_Msg_Blank_Conditional;
|
|
Get_Unqualified_Decoded_Name_String (Error_Msg_Name_1);
|
|
|
|
-- Remove %s or %b at end. These come from unit names. If the
|
|
-- caller wanted the (unit) or (body), then they would have used
|
|
-- the $ insertion character. Certainly no error message should
|
|
-- ever have %b or %s explicitly occurring.
|
|
|
|
if Name_Len > 2
|
|
and then Name_Buffer (Name_Len - 1) = '%'
|
|
and then (Name_Buffer (Name_Len) = 'b'
|
|
or else
|
|
Name_Buffer (Name_Len) = 's')
|
|
then
|
|
Name_Len := Name_Len - 2;
|
|
end if;
|
|
|
|
-- Remove upper case letter at end, again, we should not be getting
|
|
-- such names, and what we hope is that the remainder makes sense.
|
|
|
|
if Name_Len > 1
|
|
and then Name_Buffer (Name_Len) in 'A' .. 'Z'
|
|
then
|
|
Name_Len := Name_Len - 1;
|
|
end if;
|
|
|
|
-- If operator name or character literal name, just print it as is
|
|
-- Also print as is if it ends in a right paren (case of x'val(nnn))
|
|
|
|
if Name_Buffer (1) = '"'
|
|
or else Name_Buffer (1) = '''
|
|
or else Name_Buffer (Name_Len) = ')'
|
|
then
|
|
Set_Msg_Name_Buffer;
|
|
|
|
-- Else output with surrounding quotes in proper casing mode
|
|
|
|
else
|
|
Set_Casing (Identifier_Casing (Flag_Source), Mixed_Case);
|
|
Set_Msg_Quote;
|
|
Set_Msg_Name_Buffer;
|
|
Set_Msg_Quote;
|
|
end if;
|
|
end if;
|
|
|
|
-- The following assignments ensure that the second and third percent
|
|
-- insertion characters will correspond to the Error_Msg_Name_2 and
|
|
-- Error_Msg_Name_3 as required.
|
|
|
|
Error_Msg_Name_1 := Error_Msg_Name_2;
|
|
Error_Msg_Name_2 := Error_Msg_Name_3;
|
|
end Set_Msg_Insertion_Name;
|
|
|
|
-------------------------------------
|
|
-- Set_Msg_Insertion_Reserved_Name --
|
|
-------------------------------------
|
|
|
|
procedure Set_Msg_Insertion_Reserved_Name is
|
|
begin
|
|
Set_Msg_Blank_Conditional;
|
|
Get_Name_String (Error_Msg_Name_1);
|
|
Set_Msg_Quote;
|
|
Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
|
|
Set_Msg_Name_Buffer;
|
|
Set_Msg_Quote;
|
|
end Set_Msg_Insertion_Reserved_Name;
|
|
|
|
-------------------------------------
|
|
-- Set_Msg_Insertion_Reserved_Word --
|
|
-------------------------------------
|
|
|
|
procedure Set_Msg_Insertion_Reserved_Word
|
|
(Text : String;
|
|
J : in out Integer)
|
|
is
|
|
begin
|
|
Set_Msg_Blank_Conditional;
|
|
Name_Len := 0;
|
|
|
|
while J <= Text'Last and then Text (J) in 'A' .. 'Z' loop
|
|
Name_Len := Name_Len + 1;
|
|
Name_Buffer (Name_Len) := Text (J);
|
|
J := J + 1;
|
|
end loop;
|
|
|
|
Set_Casing (Keyword_Casing (Flag_Source), All_Lower_Case);
|
|
Set_Msg_Quote;
|
|
Set_Msg_Name_Buffer;
|
|
Set_Msg_Quote;
|
|
end Set_Msg_Insertion_Reserved_Word;
|
|
|
|
-------------------------------------
|
|
-- Set_Msg_Insertion_Run_Time_Name --
|
|
-------------------------------------
|
|
|
|
procedure Set_Msg_Insertion_Run_Time_Name is
|
|
begin
|
|
if Targparm.Run_Time_Name_On_Target /= No_Name then
|
|
Set_Msg_Blank_Conditional;
|
|
Set_Msg_Char ('(');
|
|
Get_Name_String (Targparm.Run_Time_Name_On_Target);
|
|
Set_Casing (Mixed_Case);
|
|
Set_Msg_Str (Name_Buffer (1 .. Name_Len));
|
|
Set_Msg_Char (')');
|
|
end if;
|
|
end Set_Msg_Insertion_Run_Time_Name;
|
|
|
|
----------------------------
|
|
-- Set_Msg_Insertion_Uint --
|
|
----------------------------
|
|
|
|
procedure Set_Msg_Insertion_Uint is
|
|
begin
|
|
Set_Msg_Blank;
|
|
UI_Image (Error_Msg_Uint_1);
|
|
|
|
for J in 1 .. UI_Image_Length loop
|
|
Set_Msg_Char (UI_Image_Buffer (J));
|
|
end loop;
|
|
|
|
-- The following assignment ensures that a second carret insertion
|
|
-- character will correspond to the Error_Msg_Uint_2 parameter.
|
|
|
|
Error_Msg_Uint_1 := Error_Msg_Uint_2;
|
|
end Set_Msg_Insertion_Uint;
|
|
|
|
-----------------
|
|
-- Set_Msg_Int --
|
|
-----------------
|
|
|
|
procedure Set_Msg_Int (Line : Int) is
|
|
begin
|
|
if Line > 9 then
|
|
Set_Msg_Int (Line / 10);
|
|
end if;
|
|
|
|
Set_Msg_Char (Character'Val (Character'Pos ('0') + (Line rem 10)));
|
|
end Set_Msg_Int;
|
|
|
|
-------------------------
|
|
-- Set_Msg_Name_Buffer --
|
|
-------------------------
|
|
|
|
procedure Set_Msg_Name_Buffer is
|
|
begin
|
|
for J in 1 .. Name_Len loop
|
|
Set_Msg_Char (Name_Buffer (J));
|
|
end loop;
|
|
end Set_Msg_Name_Buffer;
|
|
|
|
-------------------
|
|
-- Set_Msg_Quote --
|
|
-------------------
|
|
|
|
procedure Set_Msg_Quote is
|
|
begin
|
|
if not Manual_Quote_Mode then
|
|
Set_Msg_Char ('"');
|
|
end if;
|
|
end Set_Msg_Quote;
|
|
|
|
-----------------
|
|
-- Set_Msg_Str --
|
|
-----------------
|
|
|
|
procedure Set_Msg_Str (Text : String) is
|
|
begin
|
|
for J in Text'Range loop
|
|
Set_Msg_Char (Text (J));
|
|
end loop;
|
|
end Set_Msg_Str;
|
|
|
|
------------------------------
|
|
-- Set_Next_Non_Deleted_Msg --
|
|
------------------------------
|
|
|
|
procedure Set_Next_Non_Deleted_Msg (E : in out Error_Msg_Id) is
|
|
begin
|
|
if E = No_Error_Msg then
|
|
return;
|
|
|
|
else
|
|
loop
|
|
E := Errors.Table (E).Next;
|
|
exit when E = No_Error_Msg or else not Errors.Table (E).Deleted;
|
|
end loop;
|
|
end if;
|
|
end Set_Next_Non_Deleted_Msg;
|
|
|
|
---------------------------
|
|
-- Set_Warnings_Mode_Off --
|
|
---------------------------
|
|
|
|
procedure Set_Warnings_Mode_Off (Loc : Source_Ptr) is
|
|
begin
|
|
-- Don't bother with entries from instantiation copies, since we
|
|
-- will already have a copy in the template, which is what matters
|
|
|
|
if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
|
|
return;
|
|
end if;
|
|
|
|
-- If last entry in table already covers us, this is a redundant
|
|
-- pragma Warnings (Off) and can be ignored. This also handles the
|
|
-- case where all warnings are suppressed by command line switch.
|
|
|
|
if Warnings.Last >= Warnings.First
|
|
and then Warnings.Table (Warnings.Last).Start <= Loc
|
|
and then Loc <= Warnings.Table (Warnings.Last).Stop
|
|
then
|
|
return;
|
|
|
|
-- Otherwise establish a new entry, extending from the location of
|
|
-- the pragma to the end of the current source file. This ending
|
|
-- point will be adjusted by a subsequent pragma Warnings (On).
|
|
|
|
else
|
|
Warnings.Increment_Last;
|
|
Warnings.Table (Warnings.Last).Start := Loc;
|
|
Warnings.Table (Warnings.Last).Stop :=
|
|
Source_Last (Current_Source_File);
|
|
end if;
|
|
end Set_Warnings_Mode_Off;
|
|
|
|
--------------------------
|
|
-- Set_Warnings_Mode_On --
|
|
--------------------------
|
|
|
|
procedure Set_Warnings_Mode_On (Loc : Source_Ptr) is
|
|
begin
|
|
-- Don't bother with entries from instantiation copies, since we
|
|
-- will already have a copy in the template, which is what matters
|
|
|
|
if Instantiation (Get_Source_File_Index (Loc)) /= No_Location then
|
|
return;
|
|
end if;
|
|
|
|
-- Nothing to do unless command line switch to suppress all warnings
|
|
-- is off, and the last entry in the warnings table covers this
|
|
-- pragma Warnings (On), in which case adjust the end point.
|
|
|
|
if (Warnings.Last >= Warnings.First
|
|
and then Warnings.Table (Warnings.Last).Start <= Loc
|
|
and then Loc <= Warnings.Table (Warnings.Last).Stop)
|
|
and then Warning_Mode /= Suppress
|
|
then
|
|
Warnings.Table (Warnings.Last).Stop := Loc;
|
|
end if;
|
|
end Set_Warnings_Mode_On;
|
|
|
|
------------------------------------
|
|
-- Test_Style_Warning_Serious_Msg --
|
|
------------------------------------
|
|
|
|
procedure Test_Style_Warning_Serious_Msg (Msg : String) is
|
|
begin
|
|
if Msg (Msg'First) = '\' then
|
|
return;
|
|
end if;
|
|
|
|
Is_Serious_Error := True;
|
|
Is_Warning_Msg := False;
|
|
|
|
Is_Style_Msg :=
|
|
(Msg'Length > 7
|
|
and then Msg (Msg'First .. Msg'First + 6) = "(style)");
|
|
|
|
for J in Msg'Range loop
|
|
if Msg (J) = '?'
|
|
and then (J = Msg'First or else Msg (J - 1) /= ''')
|
|
then
|
|
Is_Warning_Msg := True;
|
|
|
|
elsif Msg (J) = '|'
|
|
and then (J = Msg'First or else Msg (J - 1) /= ''')
|
|
then
|
|
Is_Serious_Error := False;
|
|
end if;
|
|
end loop;
|
|
|
|
if Is_Warning_Msg or else Is_Style_Msg then
|
|
Is_Serious_Error := False;
|
|
end if;
|
|
end Test_Style_Warning_Serious_Msg;
|
|
|
|
-------------------------
|
|
-- Warnings_Suppressed --
|
|
-------------------------
|
|
|
|
function Warnings_Suppressed (Loc : Source_Ptr) return Boolean is
|
|
begin
|
|
for J in Warnings.First .. Warnings.Last loop
|
|
if Warnings.Table (J).Start <= Loc
|
|
and then Loc <= Warnings.Table (J).Stop
|
|
then
|
|
return True;
|
|
end if;
|
|
end loop;
|
|
|
|
return False;
|
|
end Warnings_Suppressed;
|
|
|
|
end Erroutc;
|