OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [tree-diagnostic.c] - Blame information for rev 684

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 684 jeremybenn
/* 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.