OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / tree-diagnostic.c
1 /* Language-independent diagnostic subroutines for the GNU Compiler
2    Collection that are only for use in the compilers proper and not
3    the driver or other programs.
4    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
5    2009, 2010 Free Software Foundation, Inc.
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "diagnostic.h"
28 #include "tree-diagnostic.h"
29 #include "langhooks.h"
30 #include "langhooks-def.h"
31 #include "vec.h"
32
33 /* Prints out, if necessary, the name of the current function
34    that caused an error.  Called from all error and warning functions.  */
35 void
36 diagnostic_report_current_function (diagnostic_context *context,
37                                     diagnostic_info *diagnostic)
38 {
39   diagnostic_report_current_module (context, diagnostic->location);
40   lang_hooks.print_error_function (context, input_filename, diagnostic);
41 }
42
43 void
44 default_tree_diagnostic_starter (diagnostic_context *context,
45                                  diagnostic_info *diagnostic)
46 {
47   diagnostic_report_current_function (context, diagnostic);
48   pp_set_prefix (context->printer, diagnostic_build_prefix (context,
49                                                             diagnostic));
50 }
51
52 /* This is a pair made of a location and the line map it originated
53    from.  It's used in the maybe_unwind_expanded_macro_loc function
54    below.  */
55 typedef struct
56 {
57   const struct line_map *map;
58   source_location where;
59 } loc_map_pair;
60
61 DEF_VEC_O (loc_map_pair);
62 DEF_VEC_ALLOC_O (loc_map_pair, heap);
63
64 /* Unwind the different macro expansions that lead to the token which
65    location is WHERE and emit diagnostics showing the resulting
66    unwound macro expansion trace.  Let's look at an example to see how
67    the trace looks like.  Suppose we have this piece of code,
68    artificially annotated with the line numbers to increase
69    legibility:
70
71     $ cat -n test.c
72       1    #define OPERATE(OPRD1, OPRT, OPRD2) \
73       2      OPRD1 OPRT OPRD2;
74       3
75       4    #define SHIFTL(A,B) \
76       5      OPERATE (A,<<,B)
77       6
78       7    #define MULT(A) \
79       8      SHIFTL (A,1)
80       9
81      10    void
82      11    g ()
83      12    {
84      13      MULT (1.0);// 1.0 << 1; <-- so this is an error.
85      14    }
86
87    Here is the diagnostic that we want the compiler to generate:
88
89     test.c: In function 'g':
90     test.c:5:14: error: invalid operands to binary << (have 'double' and 'int')
91     test.c:2:9: note: in expansion of macro 'OPERATE'
92     test.c:5:3: note: expanded from here
93     test.c:5:14: note: in expansion of macro 'SHIFTL'
94     test.c:8:3: note: expanded from here
95     test.c:8:3: note: in expansion of macro 'MULT2'
96     test.c:13:3: note: expanded from here
97
98    The part that goes from the third to the eighth line of this
99    diagnostic (the lines containing the 'note:' string) is called the
100    unwound macro expansion trace.  That's the part generated by this
101    function.
102
103    If FIRST_EXP_POINT_MAP is non-null, *FIRST_EXP_POINT_MAP is set to
104    the map of the location in the source that first triggered the
105    macro expansion.  This must be an ordinary map.  */
106
107 static void
108 maybe_unwind_expanded_macro_loc (diagnostic_context *context,
109                                  diagnostic_info *diagnostic,
110                                  source_location where,
111                                  const struct line_map **first_exp_point_map)
112 {
113   const struct line_map *map;
114   VEC(loc_map_pair,heap) *loc_vec = NULL;
115   unsigned ix;
116   loc_map_pair loc, *iter;
117
118   map = linemap_lookup (line_table, where);
119   if (!linemap_macro_expansion_map_p (map))
120     return;
121
122   /* Let's unwind the macros that got expanded and led to the token
123      which location is WHERE.  We are going to store these macros into
124      LOC_VEC, so that we can later walk it at our convenience to
125      display a somewhat meaningful trace of the macro expansion
126      history to the user.  Note that the first macro of the trace
127      (which is OPERATE in the example above) is going to be stored at
128      the beginning of LOC_VEC.  */
129
130   do
131     {
132       loc.where = where;
133       loc.map = map;
134
135       VEC_safe_push (loc_map_pair, heap, loc_vec, &loc);
136
137       /* WHERE is the location of a token inside the expansion of a
138          macro.  MAP is the map holding the locations of that macro
139          expansion.  Let's get the location of the token inside the
140          context that triggered the expansion of this macro.
141          This is basically how we go "down" in the trace of macro
142          expansions that led to WHERE.  */
143       where = linemap_unwind_toward_expansion (line_table, where, &map);
144     } while (linemap_macro_expansion_map_p (map));
145
146   if (first_exp_point_map)
147     *first_exp_point_map = map;
148
149   /* Walk LOC_VEC and print the macro expansion trace, unless the
150      first macro which expansion triggered this trace was expanded
151      inside a system header.  */
152   if (!LINEMAP_SYSP (map))
153     FOR_EACH_VEC_ELT (loc_map_pair, loc_vec, ix, iter)
154       {
155         source_location resolved_def_loc = 0, resolved_exp_loc = 0;
156         diagnostic_t saved_kind;
157         const char *saved_prefix;
158         source_location saved_location;
159
160         /* Okay, now here is what we want.  For each token resulting
161            from macro expansion we want to show: 1/ where in the
162            definition of the macro the token comes from; 2/ where the
163            macro got expanded.  */
164
165         /* Resolve the location iter->where into the locus 1/ of the
166            comment above.  */
167         resolved_def_loc =
168           linemap_resolve_location (line_table, iter->where,
169                                     LRK_MACRO_DEFINITION_LOCATION, NULL);
170
171         /* Resolve the location of the expansion point of the macro
172            which expansion gave the token represented by def_loc.
173            This is the locus 2/ of the earlier comment.  */
174         resolved_exp_loc =
175           linemap_resolve_location (line_table,
176                                     MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map),
177                                     LRK_MACRO_DEFINITION_LOCATION, NULL);
178
179         saved_kind = diagnostic->kind;
180         saved_prefix = context->printer->prefix;
181         saved_location = diagnostic->location;
182
183         diagnostic->kind = DK_NOTE;
184         diagnostic->location = resolved_def_loc;
185         pp_base_set_prefix (context->printer,
186                             diagnostic_build_prefix (context,
187                                                      diagnostic));
188         pp_newline (context->printer);
189         pp_printf (context->printer, "in expansion of macro '%s'",
190                    linemap_map_get_macro_name (iter->map));
191         pp_destroy_prefix (context->printer);
192
193         diagnostic->location = resolved_exp_loc;
194         pp_base_set_prefix (context->printer,
195                             diagnostic_build_prefix (context,
196                                                      diagnostic));
197         pp_newline (context->printer);
198         pp_printf (context->printer, "expanded from here");
199         pp_destroy_prefix (context->printer);
200
201         diagnostic->kind = saved_kind;
202         diagnostic->location = saved_location;
203         context->printer->prefix = saved_prefix;
204       }
205
206   VEC_free (loc_map_pair, heap, loc_vec);
207 }
208
209 /*  This is a diagnostic finalizer implementation that is aware of
210     virtual locations produced by libcpp.
211
212     It has to be called by the diagnostic finalizer of front ends that
213     uses libcpp and wish to get diagnostics involving tokens resulting
214     from macro expansion.
215
216     For a given location, if said location belongs to a token
217     resulting from a macro expansion, this starter prints the context
218     of the token.  E.g, for multiply nested macro expansion, it
219     unwinds the nested macro expansions and prints them in a manner
220     that is similar to what is done for function call stacks, or
221     template instantiation contexts.  */
222 void
223 virt_loc_aware_diagnostic_finalizer (diagnostic_context *context,
224                                      diagnostic_info *diagnostic)
225 {
226   maybe_unwind_expanded_macro_loc (context, diagnostic,
227                                    diagnostic->location,
228                                    NULL);
229 }