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