2015-05-01 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / gcc / ada / comperr.adb
blobcabc028417bd8f2d9e2b4107933fc07e0ab8e54e
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- C O M P E R R --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2014, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by AdaCore. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- This package contains routines called when a fatal internal compiler error
27 -- is detected. Calls to these routines cause termination of the current
28 -- compilation with appropriate error output.
30 with Atree; use Atree;
31 with Debug; use Debug;
32 with Errout; use Errout;
33 with Gnatvsn; use Gnatvsn;
34 with Lib; use Lib;
35 with Namet; use Namet;
36 with Opt; use Opt;
37 with Osint; use Osint;
38 with Output; use Output;
39 with Sinfo; use Sinfo;
40 with Sinput; use Sinput;
41 with Sprint; use Sprint;
42 with Sdefault; use Sdefault;
43 with Targparm; use Targparm;
44 with Treepr; use Treepr;
45 with Types; use Types;
47 with Ada.Exceptions; use Ada.Exceptions;
49 with System.OS_Lib; use System.OS_Lib;
50 with System.Soft_Links; use System.Soft_Links;
52 package body Comperr is
54 ----------------
55 -- Local Data --
56 ----------------
58 Abort_In_Progress : Boolean := False;
59 -- Used to prevent runaway recursion if something segfaults
60 -- while processing a previous abort.
62 -----------------------
63 -- Local Subprograms --
64 -----------------------
66 procedure Repeat_Char (Char : Character; Col : Nat; After : Character);
67 -- Output Char until current column is at or past Col, and then output
68 -- the character given by After (if column is already past Col on entry,
69 -- then the effect is simply to output the After character).
71 --------------------
72 -- Compiler_Abort --
73 --------------------
75 procedure Compiler_Abort
76 (X : String;
77 Fallback_Loc : String := "";
78 From_GCC : Boolean := False)
80 -- The procedures below output a "bug box" with information about
81 -- the cause of the compiler abort and about the preferred method
82 -- of reporting bugs. The default is a bug box appropriate for
83 -- the FSF version of GNAT, but there are specializations for
84 -- the GNATPRO and Public releases by AdaCore.
86 XF : constant Positive := X'First;
87 -- Start index, usually 1, but we won't assume this
89 procedure End_Line;
90 -- Add blanks up to column 76, and then a final vertical bar
92 --------------
93 -- End_Line --
94 --------------
96 procedure End_Line is
97 begin
98 Repeat_Char (' ', 76, '|');
99 Write_Eol;
100 end End_Line;
102 Is_GPL_Version : constant Boolean := Gnatvsn.Build_Type = GPL;
103 Is_FSF_Version : constant Boolean := Gnatvsn.Build_Type = FSF;
105 -- Start of processing for Compiler_Abort
107 begin
108 Cancel_Special_Output;
110 -- Prevent recursion through Compiler_Abort, e.g. via SIGSEGV
112 if Abort_In_Progress then
113 Exit_Program (E_Abort);
114 end if;
116 Abort_In_Progress := True;
118 -- Generate a "standard" error message instead of a bug box in case
119 -- of .NET compiler, since we do not support all constructs of the
120 -- language. Of course ideally, we should detect this before bombing on
121 -- e.g. an assertion error, but in practice most of these bombs are due
122 -- to a legitimate case of a construct not being supported (in a sense
123 -- they all are, since for sure we are not supporting something if we
124 -- bomb). By giving this message, we provide a more reasonable practical
125 -- interface, since giving scary bug boxes on unsupported features is
126 -- definitely not helpful.
128 -- Similarly if we are generating SCIL, an error message is sufficient
129 -- instead of generating a bug box.
131 -- Note that the call to Error_Msg_N below sets Serious_Errors_Detected
132 -- to 1, so we use the regular mechanism below in order to display a
133 -- "compilation abandoned" message and exit, so we still know we have
134 -- this case (and -gnatdk can still be used to get the bug box).
136 if (VM_Target = CLI_Target or else CodePeer_Mode)
137 and then Serious_Errors_Detected = 0
138 and then not Debug_Flag_K
139 and then Sloc (Current_Error_Node) > No_Location
140 then
141 if VM_Target = CLI_Target then
142 Error_Msg_N
143 ("unsupported construct in this context",
144 Current_Error_Node);
145 else
146 Error_Msg_N ("cannot generate 'S'C'I'L", Current_Error_Node);
147 end if;
148 end if;
150 -- If we are in CodePeer mode, we must also delete SCIL files
152 if CodePeer_Mode then
153 Delete_SCIL_Files;
154 end if;
156 -- If any errors have already occurred, then we guess that the abort
157 -- may well be caused by previous errors, and we don't make too much
158 -- fuss about it, since we want to let programmer fix the errors first.
160 -- Debug flag K disables this behavior (useful for debugging)
162 if Serious_Errors_Detected /= 0 and then not Debug_Flag_K then
163 Errout.Finalize (Last_Call => True);
164 Errout.Output_Messages;
166 Set_Standard_Error;
167 Write_Str ("compilation abandoned due to previous error");
168 Write_Eol;
170 Set_Standard_Output;
171 Source_Dump;
172 Tree_Dump;
173 Exit_Program (E_Errors);
175 -- Otherwise give message with details of the abort
177 else
178 Set_Standard_Error;
180 -- Generate header for bug box
182 Write_Char ('+');
183 Repeat_Char ('=', 29, 'G');
184 Write_Str ("NAT BUG DETECTED");
185 Repeat_Char ('=', 76, '+');
186 Write_Eol;
188 -- Output GNAT version identification
190 Write_Str ("| ");
191 Write_Str (Gnat_Version_String);
192 Write_Str (" (");
194 -- Output target name, deleting junk final reverse slash
196 if Target_Name.all (Target_Name.all'Last) = '\'
197 or else Target_Name.all (Target_Name.all'Last) = '/'
198 then
199 Write_Str (Target_Name.all (1 .. Target_Name.all'Last - 1));
200 else
201 Write_Str (Target_Name.all);
202 end if;
204 -- Output identification of error
206 Write_Str (") ");
208 if X'Length + Column > 76 then
209 if From_GCC then
210 Write_Str ("GCC error:");
211 end if;
213 End_Line;
215 Write_Str ("| ");
216 end if;
218 if X'Length > 70 then
219 declare
220 Last_Blank : Integer := 70;
222 begin
223 for P in 39 .. 68 loop
224 if X (XF + P) = ' ' then
225 Last_Blank := P;
226 end if;
227 end loop;
229 Write_Str (X (XF .. XF - 1 + Last_Blank));
230 End_Line;
231 Write_Str ("| ");
232 Write_Str (X (XF + Last_Blank .. X'Last));
233 end;
234 else
235 Write_Str (X);
236 end if;
238 if not From_GCC then
240 -- For exception case, get exception message from the TSD. Note
241 -- that it would be neater and cleaner to pass the exception
242 -- message (obtained from Exception_Message) as a parameter to
243 -- Compiler_Abort, but we can't do this quite yet since it would
244 -- cause bootstrap path problems for 3.10 to 3.11.
246 Write_Char (' ');
247 Write_Str (Exception_Message (Get_Current_Excep.all.all));
248 end if;
250 End_Line;
252 -- Output source location information
254 if Sloc (Current_Error_Node) <= No_Location then
255 if Fallback_Loc'Length > 0 then
256 Write_Str ("| Error detected around ");
257 Write_Str (Fallback_Loc);
258 else
259 Write_Str ("| No source file position information available");
260 end if;
262 End_Line;
263 else
264 Write_Str ("| Error detected at ");
265 Write_Location (Sloc (Current_Error_Node));
266 End_Line;
267 end if;
269 -- There are two cases now. If the file gnat_bug.box exists,
270 -- we use the contents of this file at this point.
272 declare
273 Lo : Source_Ptr;
274 Hi : Source_Ptr;
275 Src : Source_Buffer_Ptr;
277 begin
278 Namet.Unlock;
279 Name_Buffer (1 .. 12) := "gnat_bug.box";
280 Name_Len := 12;
281 Read_Source_File (Name_Enter, 0, Hi, Src);
283 -- If we get a Src file, we use it
285 if Src /= null then
286 Lo := 0;
288 Outer : while Lo < Hi loop
289 Write_Str ("| ");
291 Inner : loop
292 exit Inner when Src (Lo) = ASCII.CR
293 or else Src (Lo) = ASCII.LF;
294 Write_Char (Src (Lo));
295 Lo := Lo + 1;
296 end loop Inner;
298 End_Line;
300 while Lo <= Hi
301 and then (Src (Lo) = ASCII.CR
302 or else Src (Lo) = ASCII.LF)
303 loop
304 Lo := Lo + 1;
305 end loop;
306 end loop Outer;
308 -- Otherwise we use the standard fixed text
310 else
311 if Is_FSF_Version then
312 Write_Str
313 ("| Please submit a bug report; see" &
314 " http://gcc.gnu.org/bugs.html.");
315 End_Line;
317 elsif Is_GPL_Version then
319 Write_Str
320 ("| Please submit a bug report by email " &
321 "to report@adacore.com.");
322 End_Line;
324 Write_Str
325 ("| GAP members can alternatively use GNAT Tracker:");
326 End_Line;
328 Write_Str
329 ("| http://www.adacore.com/ " &
330 "section 'send a report'.");
331 End_Line;
333 Write_Str
334 ("| See gnatinfo.txt for full info on procedure " &
335 "for submitting bugs.");
336 End_Line;
338 else
339 Write_Str
340 ("| Please submit a bug report using GNAT Tracker:");
341 End_Line;
343 Write_Str
344 ("| http://www.adacore.com/gnattracker/ " &
345 "section 'send a report'.");
346 End_Line;
348 Write_Str
349 ("| alternatively submit a bug report by email " &
350 "to report@adacore.com,");
351 End_Line;
353 Write_Str
354 ("| including your customer number #nnn " &
355 "in the subject line.");
356 End_Line;
357 end if;
359 Write_Str
360 ("| Use a subject line meaningful to you" &
361 " and us to track the bug.");
362 End_Line;
364 Write_Str
365 ("| Include the entire contents of this bug " &
366 "box in the report.");
367 End_Line;
369 Write_Str
370 ("| Include the exact command that you entered.");
371 End_Line;
373 Write_Str
374 ("| Also include sources listed below.");
375 End_Line;
377 if not Is_FSF_Version then
378 Write_Str
379 ("| Use plain ASCII or MIME attachment(s).");
380 End_Line;
381 end if;
382 end if;
383 end;
385 -- Complete output of bug box
387 Write_Char ('+');
388 Repeat_Char ('=', 76, '+');
389 Write_Eol;
391 if Debug_Flag_3 then
392 Write_Eol;
393 Write_Eol;
394 Print_Tree_Node (Current_Error_Node);
395 Write_Eol;
396 end if;
398 Write_Eol;
400 Write_Line ("Please include these source files with error report");
401 Write_Line ("Note that list may not be accurate in some cases, ");
402 Write_Line ("so please double check that the problem can still ");
403 Write_Line ("be reproduced with the set of files listed.");
404 Write_Line ("Consider also -gnatd.n switch (see debug.adb).");
405 Write_Eol;
407 begin
408 Dump_Source_File_Names;
410 -- If we blow up trying to print the list of file names, just output
411 -- informative msg and continue.
413 exception
414 when others =>
415 Write_Str ("list may be incomplete");
416 end;
418 Write_Eol;
419 Set_Standard_Output;
421 Tree_Dump;
422 Source_Dump;
423 raise Unrecoverable_Error;
424 end if;
425 end Compiler_Abort;
427 -----------------------
428 -- Delete_SCIL_Files --
429 -----------------------
431 procedure Delete_SCIL_Files is
432 Main : Node_Id;
433 Unit_Name : Node_Id;
435 Success : Boolean;
436 pragma Unreferenced (Success);
438 procedure Decode_Name_Buffer;
439 -- Replace "__" by "." in Name_Buffer, and adjust Name_Len accordingly
441 ------------------------
442 -- Decode_Name_Buffer --
443 ------------------------
445 procedure Decode_Name_Buffer is
446 J : Natural;
447 K : Natural;
449 begin
450 J := 1;
451 K := 0;
452 while J <= Name_Len loop
453 K := K + 1;
455 if J < Name_Len
456 and then Name_Buffer (J) = '_'
457 and then Name_Buffer (J + 1) = '_'
458 then
459 Name_Buffer (K) := '.';
460 J := J + 1;
461 else
462 Name_Buffer (K) := Name_Buffer (J);
463 end if;
465 J := J + 1;
466 end loop;
468 Name_Len := K;
469 end Decode_Name_Buffer;
471 -- Start of processing for Delete_SCIL_Files
473 begin
474 -- If parsing was not successful, no Main_Unit is available, so return
475 -- immediately.
477 if Main_Source_File = No_Source_File then
478 return;
479 end if;
481 -- Retrieve unit name, and remove old versions of SCIL/<unit>.scil and
482 -- SCIL/<unit>__body.scil, ditto for .scilx files.
484 Main := Unit (Cunit (Main_Unit));
486 case Nkind (Main) is
487 when N_Subprogram_Body | N_Package_Declaration =>
488 Unit_Name := Defining_Unit_Name (Specification (Main));
490 when N_Package_Body =>
491 Unit_Name := Corresponding_Spec (Main);
493 when N_Package_Renaming_Declaration =>
494 Unit_Name := Defining_Unit_Name (Main);
496 -- No SCIL file generated for generic package declarations
498 when N_Generic_Package_Declaration =>
499 return;
501 -- Should never happen, but can be ignored in production
503 when others =>
504 pragma Assert (False);
505 return;
506 end case;
508 case Nkind (Unit_Name) is
509 when N_Defining_Identifier =>
510 Get_Name_String (Chars (Unit_Name));
512 when N_Defining_Program_Unit_Name =>
513 Get_Name_String (Chars (Defining_Identifier (Unit_Name)));
514 Decode_Name_Buffer;
516 -- Should never happen, but can be ignored in production
518 when others =>
519 pragma Assert (False);
520 return;
521 end case;
523 Delete_File
524 ("SCIL/" & Name_Buffer (1 .. Name_Len) & ".scil", Success);
525 Delete_File
526 ("SCIL/" & Name_Buffer (1 .. Name_Len) & ".scilx", Success);
527 Delete_File
528 ("SCIL/" & Name_Buffer (1 .. Name_Len) & "__body.scil", Success);
529 Delete_File
530 ("SCIL/" & Name_Buffer (1 .. Name_Len) & "__body.scilx", Success);
531 end Delete_SCIL_Files;
533 -----------------
534 -- Repeat_Char --
535 -----------------
537 procedure Repeat_Char (Char : Character; Col : Nat; After : Character) is
538 begin
539 while Column < Col loop
540 Write_Char (Char);
541 end loop;
543 Write_Char (After);
544 end Repeat_Char;
546 end Comperr;