OSDN Git Service

2009-05-06 Gary Dismukes <dismukes@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / comperr.adb
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-2009, 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 ------------------------------------------------------------------------------
25
26 --  This package contains routines called when a fatal internal compiler
27 --  error is detected. Calls to these routines cause termination of the
28 --  current compilation with appropriate error output.
29
30 with Atree;    use Atree;
31 with Debug;    use Debug;
32 with Errout;   use Errout;
33 with Gnatvsn;  use Gnatvsn;
34 with Namet;    use Namet;
35 with Osint;    use Osint;
36 with Output;   use Output;
37 with Sinput;   use Sinput;
38 with Sprint;   use Sprint;
39 with Sdefault; use Sdefault;
40 with Targparm; use Targparm;
41 with Treepr;   use Treepr;
42 with Types;    use Types;
43
44 with Ada.Exceptions; use Ada.Exceptions;
45
46 with System.Soft_Links; use System.Soft_Links;
47
48 package body Comperr is
49
50    ----------------
51    -- Local Data --
52    ----------------
53
54    Abort_In_Progress : Boolean := False;
55    --  Used to prevent runaway recursion if something segfaults
56    --  while processing a previous abort.
57
58    -----------------------
59    -- Local Subprograms --
60    -----------------------
61
62    procedure Repeat_Char (Char : Character; Col : Nat; After : Character);
63    --  Output Char until current column is at or past Col, and then output
64    --  the character given by After (if column is already past Col on entry,
65    --  then the effect is simply to output the After character).
66
67    --------------------
68    -- Compiler_Abort --
69    --------------------
70
71    procedure Compiler_Abort
72      (X            : String;
73       Code         : Integer := 0;
74       Fallback_Loc : String := "")
75    is
76       --  The procedures below output a "bug box" with information about
77       --  the cause of the compiler abort and about the preferred method
78       --  of reporting bugs. The default is a bug box appropriate for
79       --  the FSF version of GNAT, but there are specializations for
80       --  the GNATPRO and Public releases by AdaCore.
81
82       XF : constant Positive := X'First;
83       --  Start index, usually 1, but we won't assume this
84
85       procedure End_Line;
86       --  Add blanks up to column 76, and then a final vertical bar
87
88       --------------
89       -- End_Line --
90       --------------
91
92       procedure End_Line is
93       begin
94          Repeat_Char (' ', 76, '|');
95          Write_Eol;
96       end End_Line;
97
98       Is_GPL_Version : constant Boolean := Gnatvsn.Build_Type = GPL;
99       Is_FSF_Version : constant Boolean := Gnatvsn.Build_Type = FSF;
100
101    --  Start of processing for Compiler_Abort
102
103    begin
104       Cancel_Special_Output;
105
106       --  Prevent recursion through Compiler_Abort, e.g. via SIGSEGV
107
108       if Abort_In_Progress then
109          Exit_Program (E_Abort);
110       end if;
111
112       Abort_In_Progress := True;
113
114       --  Generate a "standard" error message instead of a bug box in case of
115       --  .NET compiler, since we do not support all constructs of the
116       --  language. Of course ideally, we should detect this before bombing
117       --  on e.g. an assertion error, but in practice most of these bombs
118       --  are due to a legitimate case of a construct not being supported (in
119       --  a sense they all are, since for sure we are not supporting something
120       --  if we bomb!) By giving this message, we provide a more reasonable
121       --  practical interface, since giving scary bug boxes on unsupported
122       --  features is definitely not helpful.
123
124       --  Note that the call to Error_Msg_N below sets Serious_Errors_Detected
125       --  to 1, so we use the regular mechanism below in order to display a
126       --  "compilation abandoned" message and exit, so we still know we have
127       --  this case (and -gnatdk can still be used to get the bug box).
128
129       if VM_Target = CLI_Target
130         and then Serious_Errors_Detected = 0
131         and then not Debug_Flag_K
132         and then Sloc (Current_Error_Node) > No_Location
133       then
134          Error_Msg_N
135            ("unsupported construct in this context",
136             Current_Error_Node);
137       end if;
138
139       --  If any errors have already occurred, then we guess that the abort
140       --  may well be caused by previous errors, and we don't make too much
141       --  fuss about it, since we want to let programmer fix the errors first.
142
143       --  Debug flag K disables this behavior (useful for debugging)
144
145       if Serious_Errors_Detected /= 0 and then not Debug_Flag_K then
146          Errout.Finalize (Last_Call => True);
147          Errout.Output_Messages;
148
149          Set_Standard_Error;
150          Write_Str ("compilation abandoned due to previous error");
151          Write_Eol;
152
153          Set_Standard_Output;
154          Source_Dump;
155          Tree_Dump;
156          Exit_Program (E_Errors);
157
158       --  Otherwise give message with details of the abort
159
160       else
161          Set_Standard_Error;
162
163          --  Generate header for bug box
164
165          Write_Char ('+');
166          Repeat_Char ('=', 29, 'G');
167          Write_Str ("NAT BUG DETECTED");
168          Repeat_Char ('=', 76, '+');
169          Write_Eol;
170
171          --  Output GNAT version identification
172
173          Write_Str ("| ");
174          Write_Str (Gnat_Version_String);
175          Write_Str (" (");
176
177          --  Output target name, deleting junk final reverse slash
178
179          if Target_Name.all (Target_Name.all'Last) = '\'
180            or else Target_Name.all (Target_Name.all'Last) = '/'
181          then
182             Write_Str (Target_Name.all (1 .. Target_Name.all'Last - 1));
183          else
184             Write_Str (Target_Name.all);
185          end if;
186
187          --  Output identification of error
188
189          Write_Str (") ");
190
191          if X'Length + Column > 76 then
192             if Code < 0 then
193                Write_Str ("GCC error:");
194             end if;
195
196             End_Line;
197
198             Write_Str ("| ");
199          end if;
200
201          if X'Length > 70 then
202             declare
203                Last_Blank : Integer := 70;
204
205             begin
206                for P in 39 .. 68 loop
207                   if X (XF + P) = ' ' then
208                      Last_Blank := P;
209                   end if;
210                end loop;
211
212                Write_Str (X (XF .. XF - 1 + Last_Blank));
213                End_Line;
214                Write_Str ("|    ");
215                Write_Str (X (XF + Last_Blank .. X'Last));
216             end;
217          else
218             Write_Str (X);
219          end if;
220
221          if Code > 0 then
222             Write_Str (", Code=");
223             Write_Int (Int (Code));
224
225          elsif Code = 0 then
226
227             --  For exception case, get exception message from the TSD. Note
228             --  that it would be neater and cleaner to pass the exception
229             --  message (obtained from Exception_Message) as a parameter to
230             --  Compiler_Abort, but we can't do this quite yet since it would
231             --  cause bootstrap path problems for 3.10 to 3.11.
232
233             Write_Char (' ');
234             Write_Str (Exception_Message (Get_Current_Excep.all.all));
235          end if;
236
237          End_Line;
238
239          --  Output source location information
240
241          if Sloc (Current_Error_Node) <= No_Location then
242             if Fallback_Loc'Length > 0 then
243                Write_Str ("| Error detected around ");
244                Write_Str (Fallback_Loc);
245             else
246                Write_Str ("| No source file position information available");
247             end if;
248
249             End_Line;
250          else
251             Write_Str ("| Error detected at ");
252             Write_Location (Sloc (Current_Error_Node));
253             End_Line;
254          end if;
255
256          --  There are two cases now. If the file gnat_bug.box exists,
257          --  we use the contents of this file at this point.
258
259          declare
260             Lo  : Source_Ptr;
261             Hi  : Source_Ptr;
262             Src : Source_Buffer_Ptr;
263
264          begin
265             Namet.Unlock;
266             Name_Buffer (1 .. 12) := "gnat_bug.box";
267             Name_Len := 12;
268             Read_Source_File (Name_Enter, 0, Hi, Src);
269
270             --  If we get a Src file, we use it
271
272             if Src /= null then
273                Lo := 0;
274
275                Outer : while Lo < Hi loop
276                   Write_Str ("| ");
277
278                   Inner : loop
279                      exit Inner when Src (Lo) = ASCII.CR
280                        or else Src (Lo) = ASCII.LF;
281                      Write_Char (Src (Lo));
282                      Lo := Lo + 1;
283                   end loop Inner;
284
285                   End_Line;
286
287                   while Lo <= Hi
288                     and then (Src (Lo) = ASCII.CR
289                                 or else Src (Lo) = ASCII.LF)
290                   loop
291                      Lo := Lo + 1;
292                   end loop;
293                end loop Outer;
294
295             --  Otherwise we use the standard fixed text
296
297             else
298                if Is_FSF_Version then
299                   Write_Str
300                     ("| Please submit a bug report; see" &
301                      " http://gcc.gnu.org/bugs.html.");
302                   End_Line;
303
304                elsif Is_GPL_Version then
305
306                   Write_Str
307                     ("| Please submit a bug report by email " &
308                      "to report@adacore.com.");
309                   End_Line;
310
311                   Write_Str
312                     ("| GAP members can alternatively use GNAT Tracker:");
313                   End_Line;
314
315                   Write_Str
316                     ("| http://www.adacore.com/ " &
317                      "section 'send a report'.");
318                   End_Line;
319
320                   Write_Str
321                     ("| See gnatinfo.txt for full info on procedure " &
322                      "for submitting bugs.");
323                   End_Line;
324
325                else
326                   Write_Str
327                     ("| Please submit a bug report using GNAT Tracker:");
328                   End_Line;
329
330                   Write_Str
331                     ("| http://www.adacore.com/gnattracker/ " &
332                      "section 'send a report'.");
333                   End_Line;
334
335                   Write_Str
336                     ("| alternatively submit a bug report by email " &
337                      "to report@adacore.com,");
338                   End_Line;
339
340                   Write_Str
341                     ("| including your customer number #nnn " &
342                      "in the subject line.");
343                   End_Line;
344                end if;
345
346                Write_Str
347                  ("| Use a subject line meaningful to you" &
348                   " and us to track the bug.");
349                End_Line;
350
351                Write_Str
352                  ("| Include the entire contents of this bug " &
353                   "box in the report.");
354                End_Line;
355
356                Write_Str
357                  ("| Include the exact gcc or gnatmake command " &
358                   "that you entered.");
359                End_Line;
360
361                Write_Str
362                  ("| Also include sources listed below in gnatchop format");
363                End_Line;
364
365                Write_Str
366                  ("| (concatenated together with no headers between files).");
367                End_Line;
368
369                if not Is_FSF_Version then
370                   Write_Str
371                     ("| Use plain ASCII or MIME attachment.");
372                   End_Line;
373                end if;
374             end if;
375          end;
376
377          --  Complete output of bug box
378
379          Write_Char ('+');
380          Repeat_Char ('=', 76, '+');
381          Write_Eol;
382
383          if Debug_Flag_3 then
384             Write_Eol;
385             Write_Eol;
386             Print_Tree_Node (Current_Error_Node);
387             Write_Eol;
388          end if;
389
390          Write_Eol;
391
392          Write_Line ("Please include these source files with error report");
393          Write_Line ("Note that list may not be accurate in some cases, ");
394          Write_Line ("so please double check that the problem can still ");
395          Write_Line ("be reproduced with the set of files listed.");
396          Write_Line ("Consider also -gnatd.n switch (see debug.adb).");
397          Write_Eol;
398
399          begin
400             Dump_Source_File_Names;
401
402          --  If we blow up trying to print the list of file names, just output
403          --  informative msg and continue.
404
405          exception
406             when others =>
407                Write_Str ("list may be incomplete");
408          end;
409
410          Write_Eol;
411          Set_Standard_Output;
412
413          Tree_Dump;
414          Source_Dump;
415          raise Unrecoverable_Error;
416       end if;
417
418    end Compiler_Abort;
419
420    -----------------
421    -- Repeat_Char --
422    -----------------
423
424    procedure Repeat_Char (Char : Character; Col : Nat; After : Character) is
425    begin
426       while Column < Col loop
427          Write_Char (Char);
428       end loop;
429
430       Write_Char (After);
431    end Repeat_Char;
432
433 end Comperr;