]> git.ipfire.org Git - thirdparty/gcc.git/blame - libcpp/line-map.c
Fix matmul PR18857 and supply testcase
[thirdparty/gcc.git] / libcpp / line-map.c
CommitLineData
d82fc108 1/* Map logical line numbers to (source file, line number) pairs.
d9221e01 2 Copyright (C) 2001, 2003, 2004
d82fc108
NB
3 Free Software Foundation, Inc.
4
5This program is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option) any
8later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding! */
22
23#include "config.h"
24#include "system.h"
25#include "line-map.h"
26
e2b9853b 27static void trace_include (const struct line_maps *, const struct line_map *);
5993019d 28
d82fc108
NB
29/* Initialize a line map set. */
30
31void
a2f7be91 32linemap_init (struct line_maps *set)
d82fc108 33{
9132fbb7 34 set->maps = NULL;
d82fc108
NB
35 set->allocated = 0;
36 set->used = 0;
fde84349 37 set->last_listed = -1;
5993019d 38 set->trace_includes = false;
d8693c6f 39 set->depth = 0;
9132fbb7 40 set->cache = 0;
12f9df4e 41 set->highest_location = 0;
500bee0a 42 set->highest_line = 0;
12f9df4e 43 set->max_column_hint = 0;
d82fc108
NB
44}
45
9ac97460 46/* Check for and warn about line_maps entered but not exited. */
12f9df4e
PB
47
48void
49linemap_check_files_exited (struct line_maps *set)
50{
51 struct line_map *map;
52 /* Depending upon whether we are handling preprocessed input or
53 not, this can be a user error or an ICE. */
54 for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
55 map = INCLUDED_FROM (set, map))
56 fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
57 map->to_file);
58}
59
d82fc108
NB
60/* Free a line map set. */
61
fde84349 62void
a2f7be91 63linemap_free (struct line_maps *set)
d82fc108
NB
64{
65 if (set->maps)
fde84349 66 {
12f9df4e 67 linemap_check_files_exited (set);
47d89cf3 68
fde84349
NB
69 free (set->maps);
70 }
d82fc108
NB
71}
72
73/* Add a mapping of logical source line to physical source file and
9074464c
GK
74 line number.
75
76 The text pointed to by TO_FILE must have a lifetime
77 at least as long as the final call to lookup_line (). An empty
78 TO_FILE means standard input. If reason is LC_LEAVE, and
79 TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
80 natural values considering the file we are returning to.
d82fc108
NB
81
82 FROM_LINE should be monotonic increasing across calls to this
9074464c 83 function. A call to this function can relocate the previous set of
12f9df4e 84 A call to this function can relocate the previous set of
9074464c 85 maps, so any stored line_map pointers should not be used. */
d82fc108 86
47d89cf3 87const struct line_map *
a2f7be91 88linemap_add (struct line_maps *set, enum lc_reason reason,
12f9df4e 89 unsigned int sysp, const char *to_file, unsigned int to_line)
d82fc108
NB
90{
91 struct line_map *map;
12f9df4e 92 source_location start_location = set->highest_location + 1;
d82fc108 93
12f9df4e 94 if (set->used && start_location < set->maps[set->used - 1].start_location)
d82fc108
NB
95 abort ();
96
97 if (set->used == set->allocated)
98 {
99 set->allocated = 2 * set->allocated + 256;
703ad42b 100 set->maps = xrealloc (set->maps, set->allocated * sizeof (struct line_map));
d82fc108
NB
101 }
102
9132fbb7 103 map = &set->maps[set->used];
d82fc108 104
9074464c
GK
105 if (to_file && *to_file == '\0')
106 to_file = "<stdin>";
107
fde84349
NB
108 /* If we don't keep our line maps consistent, we can easily
109 segfault. Don't rely on the client to do it for us. */
d8693c6f 110 if (set->depth == 0)
fde84349
NB
111 reason = LC_ENTER;
112 else if (reason == LC_LEAVE)
113 {
47d89cf3
NB
114 struct line_map *from;
115 bool error;
116
117 if (MAIN_FILE_P (map - 1))
fde84349 118 {
b3147029
PB
119 if (to_file == NULL)
120 {
121 set->depth--;
b3147029
PB
122 return NULL;
123 }
124 error = true;
125 reason = LC_RENAME;
126 from = map - 1;
47d89cf3
NB
127 }
128 else
129 {
130 from = INCLUDED_FROM (set, map - 1);
131 error = to_file && strcmp (from->to_file, to_file);
132 }
133
134 /* Depending upon whether we are handling preprocessed input or
135 not, this can be a user error or an ICE. */
136 if (error)
137 fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
138 to_file);
139
140 /* A TO_FILE of NULL is special - we use the natural values. */
141 if (error || to_file == NULL)
142 {
143 to_file = from->to_file;
12f9df4e 144 to_line = SOURCE_LINE (from, from[1].start_location);
47d89cf3 145 sysp = from->sysp;
fde84349
NB
146 }
147 }
148
47d89cf3
NB
149 map->reason = reason;
150 map->sysp = sysp;
12f9df4e 151 map->start_location = start_location;
47d89cf3
NB
152 map->to_file = to_file;
153 map->to_line = to_line;
9132fbb7 154 set->cache = set->used++;
12f9df4e
PB
155 map->column_bits = 0;
156 set->highest_location = start_location;
500bee0a 157 set->highest_line = start_location;
12f9df4e 158 set->max_column_hint = 0;
47d89cf3 159
fde84349 160 if (reason == LC_ENTER)
d8693c6f 161 {
8826ff0f 162 map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
d8693c6f 163 set->depth++;
d8693c6f
NB
164 if (set->trace_includes)
165 trace_include (set, map);
166 }
d82fc108
NB
167 else if (reason == LC_RENAME)
168 map->included_from = map[-1].included_from;
169 else if (reason == LC_LEAVE)
d8693c6f
NB
170 {
171 set->depth--;
172 map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
173 }
5993019d 174
d82fc108
NB
175 return map;
176}
177
12f9df4e
PB
178source_location
179linemap_line_start (struct line_maps *set, unsigned int to_line,
180 unsigned int max_column_hint)
181{
182 struct line_map *map = &set->maps[set->used - 1];
183 source_location highest = set->highest_location;
184 source_location r;
500bee0a 185 unsigned int last_line = SOURCE_LINE (map, set->highest_line);
12f9df4e
PB
186 int line_delta = to_line - last_line;
187 bool add_map = false;
188 if (line_delta < 0
189 || (line_delta > 10 && line_delta * map->column_bits > 1000)
190 || (max_column_hint >= (1U << map->column_bits))
191 || (max_column_hint <= 80 && map->column_bits >= 10))
192 {
193 add_map = true;
194 }
195 else
196 max_column_hint = set->max_column_hint;
197 if (add_map)
198 {
199 int column_bits;
500bee0a 200 if (max_column_hint > 100000 || highest > 0xC0000000)
12f9df4e 201 {
c1fc5047
PB
202 /* If the column number is ridiculous or we've allocated a huge
203 number of source_locations, give up on column numbers. */
12f9df4e
PB
204 max_column_hint = 0;
205 if (highest >0xF0000000)
206 return 0;
207 column_bits = 0;
208 }
209 else
210 {
211 column_bits = 7;
212 while (max_column_hint >= (1U << column_bits))
213 column_bits++;
214 max_column_hint = 1U << column_bits;
215 }
c1fc5047
PB
216 /* Allocate the new line_map. However, if the current map only has a
217 single line we can sometimes just increase its column_bits instead. */
12f9df4e
PB
218 if (line_delta < 0
219 || last_line != map->to_line
220 || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
221 map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
222 map->to_file, to_line);
223 map->column_bits = column_bits;
c1fc5047 224 r = map->start_location + ((to_line - map->to_line) << column_bits);
12f9df4e
PB
225 }
226 else
227 r = highest - SOURCE_COLUMN (map, highest)
228 + (line_delta << map->column_bits);
500bee0a 229 set->highest_line = r;
12f9df4e
PB
230 if (r > set->highest_location)
231 set->highest_location = r;
232 set->max_column_hint = max_column_hint;
233 return r;
234}
235
500bee0a
PB
236source_location
237linemap_position_for_column (struct line_maps *set, unsigned int to_column)
238{
239 source_location r = set->highest_line;
240 if (to_column >= set->max_column_hint)
241 {
242 if (r >= 0xC000000 || to_column > 100000)
243 {
244 /* Running low on source_locations - disable column numbers. */
245 return r;
246 }
247 else
248 {
249 struct line_map *map = &set->maps[set->used - 1];
250 r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
251 }
252 }
253 r = r + to_column;
254 if (r >= set->highest_location)
255 set->highest_location = r;
256 return r;
257}
258
6604e6f3
NB
259/* Given a logical line, returns the map from which the corresponding
260 (source file, line) pair can be deduced. Since the set is built
261 chronologically, the logical lines are monotonic increasing, and so
262 the list is sorted and we can use a binary search. */
d82fc108 263
47d89cf3 264const struct line_map *
7d40b45f 265linemap_lookup (struct line_maps *set, source_location line)
d82fc108 266{
9132fbb7
PB
267 unsigned int md, mn, mx;
268 const struct line_map *cached;
269
270 mn = set->cache;
271 mx = set->used;
272
273 cached = &set->maps[mn];
9ac97460 274 /* We should get a segfault if no line_maps have been added yet. */
12f9df4e 275 if (line >= cached->start_location)
9132fbb7 276 {
12f9df4e 277 if (mn + 1 == mx || line < cached[1].start_location)
9132fbb7
PB
278 return cached;
279 }
280 else
281 {
282 mx = mn;
283 mn = 0;
284 }
d82fc108
NB
285
286 while (mx - mn > 1)
287 {
288 md = (mn + mx) / 2;
12f9df4e 289 if (set->maps[md].start_location > line)
d82fc108
NB
290 mx = md;
291 else
292 mn = md;
293 }
294
9132fbb7 295 set->cache = mn;
d82fc108
NB
296 return &set->maps[mn];
297}
fde84349
NB
298
299/* Print the file names and line numbers of the #include commands
300 which led to the map MAP, if any, to stderr. Nothing is output if
301 the most recently listed stack is the same as the current one. */
302
303void
a2f7be91
ZW
304linemap_print_containing_files (struct line_maps *set,
305 const struct line_map *map)
fde84349
NB
306{
307 if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
308 return;
309
310 set->last_listed = map->included_from;
311 map = INCLUDED_FROM (set, map);
312
313 fprintf (stderr, _("In file included from %s:%u"),
314 map->to_file, LAST_SOURCE_LINE (map));
315
316 while (! MAIN_FILE_P (map))
317 {
318 map = INCLUDED_FROM (set, map);
319 /* Translators note: this message is used in conjunction
320 with "In file included from %s:%ld" and some other
321 tricks. We want something like this:
322
323 | In file included from sys/select.h:123,
324 | from sys/types.h:234,
325 | from userfile.c:31:
326 | bits/select.h:45: <error message here>
327
328 with all the "from"s lined up.
329 The trailing comma is at the beginning of this message,
330 and the trailing colon is not translated. */
331 fprintf (stderr, _(",\n from %s:%u"),
332 map->to_file, LAST_SOURCE_LINE (map));
333 }
334
335 fputs (":\n", stderr);
336}
5993019d
NB
337
338/* Print an include trace, for e.g. the -H option of the preprocessor. */
339
340static void
e2b9853b 341trace_include (const struct line_maps *set, const struct line_map *map)
5993019d 342{
d8693c6f 343 unsigned int i = set->depth;
5993019d 344
d8693c6f 345 while (--i)
5993019d
NB
346 putc ('.', stderr);
347 fprintf (stderr, " %s\n", map->to_file);
348}