annotate gcc/input.c @ 127:4c56639505ff

fix function.c and add CbC-example Makefile
author mir3636
date Wed, 11 Apr 2018 18:46:58 +0900
parents 04ced10e8804
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 /* Data and functions related to line maps and input files.
111
kono
parents: 68
diff changeset
2 Copyright (C) 2004-2017 Free Software Foundation, Inc.
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 This file is part of GCC.
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 GCC is free software; you can redistribute it and/or modify it under
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 the terms of the GNU General Public License as published by the Free
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 Software Foundation; either version 3, or (at your option) any later
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 version.
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 for more details.
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 You should have received a copy of the GNU General Public License
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 along with GCC; see the file COPYING3. If not see
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 <http://www.gnu.org/licenses/>. */
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20 #include "config.h"
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 #include "system.h"
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 #include "coretypes.h"
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 #include "intl.h"
111
kono
parents: 68
diff changeset
24 #include "diagnostic-core.h"
kono
parents: 68
diff changeset
25 #include "selftest.h"
kono
parents: 68
diff changeset
26 #include "cpplib.h"
kono
parents: 68
diff changeset
27
kono
parents: 68
diff changeset
28 #ifndef HAVE_ICONV
kono
parents: 68
diff changeset
29 #define HAVE_ICONV 0
kono
parents: 68
diff changeset
30 #endif
kono
parents: 68
diff changeset
31
kono
parents: 68
diff changeset
32 /* This is a cache used by get_next_line to store the content of a
kono
parents: 68
diff changeset
33 file to be searched for file lines. */
kono
parents: 68
diff changeset
34 struct fcache
kono
parents: 68
diff changeset
35 {
kono
parents: 68
diff changeset
36 /* These are information used to store a line boundary. */
kono
parents: 68
diff changeset
37 struct line_info
kono
parents: 68
diff changeset
38 {
kono
parents: 68
diff changeset
39 /* The line number. It starts from 1. */
kono
parents: 68
diff changeset
40 size_t line_num;
kono
parents: 68
diff changeset
41
kono
parents: 68
diff changeset
42 /* The position (byte count) of the beginning of the line,
kono
parents: 68
diff changeset
43 relative to the file data pointer. This starts at zero. */
kono
parents: 68
diff changeset
44 size_t start_pos;
kono
parents: 68
diff changeset
45
kono
parents: 68
diff changeset
46 /* The position (byte count) of the last byte of the line. This
kono
parents: 68
diff changeset
47 normally points to the '\n' character, or to one byte after the
kono
parents: 68
diff changeset
48 last byte of the file, if the file doesn't contain a '\n'
kono
parents: 68
diff changeset
49 character. */
kono
parents: 68
diff changeset
50 size_t end_pos;
kono
parents: 68
diff changeset
51
kono
parents: 68
diff changeset
52 line_info (size_t l, size_t s, size_t e)
kono
parents: 68
diff changeset
53 : line_num (l), start_pos (s), end_pos (e)
kono
parents: 68
diff changeset
54 {}
kono
parents: 68
diff changeset
55
kono
parents: 68
diff changeset
56 line_info ()
kono
parents: 68
diff changeset
57 :line_num (0), start_pos (0), end_pos (0)
kono
parents: 68
diff changeset
58 {}
kono
parents: 68
diff changeset
59 };
kono
parents: 68
diff changeset
60
kono
parents: 68
diff changeset
61 /* The number of time this file has been accessed. This is used
kono
parents: 68
diff changeset
62 to designate which file cache to evict from the cache
kono
parents: 68
diff changeset
63 array. */
kono
parents: 68
diff changeset
64 unsigned use_count;
kono
parents: 68
diff changeset
65
kono
parents: 68
diff changeset
66 /* The file_path is the key for identifying a particular file in
kono
parents: 68
diff changeset
67 the cache.
kono
parents: 68
diff changeset
68 For libcpp-using code, the underlying buffer for this field is
kono
parents: 68
diff changeset
69 owned by the corresponding _cpp_file within the cpp_reader. */
kono
parents: 68
diff changeset
70 const char *file_path;
kono
parents: 68
diff changeset
71
kono
parents: 68
diff changeset
72 FILE *fp;
kono
parents: 68
diff changeset
73
kono
parents: 68
diff changeset
74 /* This points to the content of the file that we've read so
kono
parents: 68
diff changeset
75 far. */
kono
parents: 68
diff changeset
76 char *data;
kono
parents: 68
diff changeset
77
kono
parents: 68
diff changeset
78 /* The size of the DATA array above.*/
kono
parents: 68
diff changeset
79 size_t size;
kono
parents: 68
diff changeset
80
kono
parents: 68
diff changeset
81 /* The number of bytes read from the underlying file so far. This
kono
parents: 68
diff changeset
82 must be less (or equal) than SIZE above. */
kono
parents: 68
diff changeset
83 size_t nb_read;
kono
parents: 68
diff changeset
84
kono
parents: 68
diff changeset
85 /* The index of the beginning of the current line. */
kono
parents: 68
diff changeset
86 size_t line_start_idx;
kono
parents: 68
diff changeset
87
kono
parents: 68
diff changeset
88 /* The number of the previous line read. This starts at 1. Zero
kono
parents: 68
diff changeset
89 means we've read no line so far. */
kono
parents: 68
diff changeset
90 size_t line_num;
kono
parents: 68
diff changeset
91
kono
parents: 68
diff changeset
92 /* This is the total number of lines of the current file. At the
kono
parents: 68
diff changeset
93 moment, we try to get this information from the line map
kono
parents: 68
diff changeset
94 subsystem. Note that this is just a hint. When using the C++
kono
parents: 68
diff changeset
95 front-end, this hint is correct because the input file is then
kono
parents: 68
diff changeset
96 completely tokenized before parsing starts; so the line map knows
kono
parents: 68
diff changeset
97 the number of lines before compilation really starts. For e.g,
kono
parents: 68
diff changeset
98 the C front-end, it can happen that we start emitting diagnostics
kono
parents: 68
diff changeset
99 before the line map has seen the end of the file. */
kono
parents: 68
diff changeset
100 size_t total_lines;
kono
parents: 68
diff changeset
101
kono
parents: 68
diff changeset
102 /* Could this file be missing a trailing newline on its final line?
kono
parents: 68
diff changeset
103 Initially true (to cope with empty files), set to true/false
kono
parents: 68
diff changeset
104 as each line is read. */
kono
parents: 68
diff changeset
105 bool missing_trailing_newline;
kono
parents: 68
diff changeset
106
kono
parents: 68
diff changeset
107 /* This is a record of the beginning and end of the lines we've seen
kono
parents: 68
diff changeset
108 while reading the file. This is useful to avoid walking the data
kono
parents: 68
diff changeset
109 from the beginning when we are asked to read a line that is
kono
parents: 68
diff changeset
110 before LINE_START_IDX above. Note that the maximum size of this
kono
parents: 68
diff changeset
111 record is fcache_line_record_size, so that the memory consumption
kono
parents: 68
diff changeset
112 doesn't explode. We thus scale total_lines down to
kono
parents: 68
diff changeset
113 fcache_line_record_size. */
kono
parents: 68
diff changeset
114 vec<line_info, va_heap> line_record;
kono
parents: 68
diff changeset
115
kono
parents: 68
diff changeset
116 fcache ();
kono
parents: 68
diff changeset
117 ~fcache ();
kono
parents: 68
diff changeset
118 };
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
119
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
120 /* Current position in real source file. */
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
121
111
kono
parents: 68
diff changeset
122 location_t input_location = UNKNOWN_LOCATION;
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
123
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
124 struct line_maps *line_table;
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
125
111
kono
parents: 68
diff changeset
126 /* A stashed copy of "line_table" for use by selftest::line_table_test.
kono
parents: 68
diff changeset
127 This needs to be a global so that it can be a GC root, and thus
kono
parents: 68
diff changeset
128 prevent the stashed copy from being garbage-collected if the GC runs
kono
parents: 68
diff changeset
129 during a line_table_test. */
kono
parents: 68
diff changeset
130
kono
parents: 68
diff changeset
131 struct line_maps *saved_line_table;
kono
parents: 68
diff changeset
132
kono
parents: 68
diff changeset
133 static fcache *fcache_tab;
kono
parents: 68
diff changeset
134 static const size_t fcache_tab_size = 16;
kono
parents: 68
diff changeset
135 static const size_t fcache_buffer_size = 4 * 1024;
kono
parents: 68
diff changeset
136 static const size_t fcache_line_record_size = 100;
kono
parents: 68
diff changeset
137
kono
parents: 68
diff changeset
138 /* Expand the source location LOC into a human readable location. If
kono
parents: 68
diff changeset
139 LOC resolves to a builtin location, the file name of the readable
kono
parents: 68
diff changeset
140 location is set to the string "<built-in>". If EXPANSION_POINT_P is
kono
parents: 68
diff changeset
141 TRUE and LOC is virtual, then it is resolved to the expansion
kono
parents: 68
diff changeset
142 point of the involved macro. Otherwise, it is resolved to the
kono
parents: 68
diff changeset
143 spelling location of the token.
kono
parents: 68
diff changeset
144
kono
parents: 68
diff changeset
145 When resolving to the spelling location of the token, if the
kono
parents: 68
diff changeset
146 resulting location is for a built-in location (that is, it has no
kono
parents: 68
diff changeset
147 associated line/column) in the context of a macro expansion, the
kono
parents: 68
diff changeset
148 returned location is the first one (while unwinding the macro
kono
parents: 68
diff changeset
149 location towards its expansion point) that is in real source
kono
parents: 68
diff changeset
150 code.
kono
parents: 68
diff changeset
151
kono
parents: 68
diff changeset
152 ASPECT controls which part of the location to use. */
kono
parents: 68
diff changeset
153
kono
parents: 68
diff changeset
154 static expanded_location
kono
parents: 68
diff changeset
155 expand_location_1 (source_location loc,
kono
parents: 68
diff changeset
156 bool expansion_point_p,
kono
parents: 68
diff changeset
157 enum location_aspect aspect)
kono
parents: 68
diff changeset
158 {
kono
parents: 68
diff changeset
159 expanded_location xloc;
kono
parents: 68
diff changeset
160 const line_map_ordinary *map;
kono
parents: 68
diff changeset
161 enum location_resolution_kind lrk = LRK_MACRO_EXPANSION_POINT;
kono
parents: 68
diff changeset
162 tree block = NULL;
kono
parents: 68
diff changeset
163
kono
parents: 68
diff changeset
164 if (IS_ADHOC_LOC (loc))
kono
parents: 68
diff changeset
165 {
kono
parents: 68
diff changeset
166 block = LOCATION_BLOCK (loc);
kono
parents: 68
diff changeset
167 loc = LOCATION_LOCUS (loc);
kono
parents: 68
diff changeset
168 }
kono
parents: 68
diff changeset
169
kono
parents: 68
diff changeset
170 memset (&xloc, 0, sizeof (xloc));
kono
parents: 68
diff changeset
171
kono
parents: 68
diff changeset
172 if (loc >= RESERVED_LOCATION_COUNT)
kono
parents: 68
diff changeset
173 {
kono
parents: 68
diff changeset
174 if (!expansion_point_p)
kono
parents: 68
diff changeset
175 {
kono
parents: 68
diff changeset
176 /* We want to resolve LOC to its spelling location.
kono
parents: 68
diff changeset
177
kono
parents: 68
diff changeset
178 But if that spelling location is a reserved location that
kono
parents: 68
diff changeset
179 appears in the context of a macro expansion (like for a
kono
parents: 68
diff changeset
180 location for a built-in token), let's consider the first
kono
parents: 68
diff changeset
181 location (toward the expansion point) that is not reserved;
kono
parents: 68
diff changeset
182 that is, the first location that is in real source code. */
kono
parents: 68
diff changeset
183 loc = linemap_unwind_to_first_non_reserved_loc (line_table,
kono
parents: 68
diff changeset
184 loc, NULL);
kono
parents: 68
diff changeset
185 lrk = LRK_SPELLING_LOCATION;
kono
parents: 68
diff changeset
186 }
kono
parents: 68
diff changeset
187 loc = linemap_resolve_location (line_table, loc, lrk, &map);
kono
parents: 68
diff changeset
188
kono
parents: 68
diff changeset
189 /* loc is now either in an ordinary map, or is a reserved location.
kono
parents: 68
diff changeset
190 If it is a compound location, the caret is in a spelling location,
kono
parents: 68
diff changeset
191 but the start/finish might still be a virtual location.
kono
parents: 68
diff changeset
192 Depending of what the caller asked for, we may need to recurse
kono
parents: 68
diff changeset
193 one level in order to resolve any virtual locations in the
kono
parents: 68
diff changeset
194 end-points. */
kono
parents: 68
diff changeset
195 switch (aspect)
kono
parents: 68
diff changeset
196 {
kono
parents: 68
diff changeset
197 default:
kono
parents: 68
diff changeset
198 gcc_unreachable ();
kono
parents: 68
diff changeset
199 /* Fall through. */
kono
parents: 68
diff changeset
200 case LOCATION_ASPECT_CARET:
kono
parents: 68
diff changeset
201 break;
kono
parents: 68
diff changeset
202 case LOCATION_ASPECT_START:
kono
parents: 68
diff changeset
203 {
kono
parents: 68
diff changeset
204 source_location start = get_start (loc);
kono
parents: 68
diff changeset
205 if (start != loc)
kono
parents: 68
diff changeset
206 return expand_location_1 (start, expansion_point_p, aspect);
kono
parents: 68
diff changeset
207 }
kono
parents: 68
diff changeset
208 break;
kono
parents: 68
diff changeset
209 case LOCATION_ASPECT_FINISH:
kono
parents: 68
diff changeset
210 {
kono
parents: 68
diff changeset
211 source_location finish = get_finish (loc);
kono
parents: 68
diff changeset
212 if (finish != loc)
kono
parents: 68
diff changeset
213 return expand_location_1 (finish, expansion_point_p, aspect);
kono
parents: 68
diff changeset
214 }
kono
parents: 68
diff changeset
215 break;
kono
parents: 68
diff changeset
216 }
kono
parents: 68
diff changeset
217 xloc = linemap_expand_location (line_table, map, loc);
kono
parents: 68
diff changeset
218 }
kono
parents: 68
diff changeset
219
kono
parents: 68
diff changeset
220 xloc.data = block;
kono
parents: 68
diff changeset
221 if (loc <= BUILTINS_LOCATION)
kono
parents: 68
diff changeset
222 xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
kono
parents: 68
diff changeset
223
kono
parents: 68
diff changeset
224 return xloc;
kono
parents: 68
diff changeset
225 }
kono
parents: 68
diff changeset
226
kono
parents: 68
diff changeset
227 /* Initialize the set of cache used for files accessed by caret
kono
parents: 68
diff changeset
228 diagnostic. */
kono
parents: 68
diff changeset
229
kono
parents: 68
diff changeset
230 static void
kono
parents: 68
diff changeset
231 diagnostic_file_cache_init (void)
kono
parents: 68
diff changeset
232 {
kono
parents: 68
diff changeset
233 if (fcache_tab == NULL)
kono
parents: 68
diff changeset
234 fcache_tab = new fcache[fcache_tab_size];
kono
parents: 68
diff changeset
235 }
kono
parents: 68
diff changeset
236
kono
parents: 68
diff changeset
237 /* Free the resources used by the set of cache used for files accessed
kono
parents: 68
diff changeset
238 by caret diagnostic. */
kono
parents: 68
diff changeset
239
kono
parents: 68
diff changeset
240 void
kono
parents: 68
diff changeset
241 diagnostic_file_cache_fini (void)
kono
parents: 68
diff changeset
242 {
kono
parents: 68
diff changeset
243 if (fcache_tab)
kono
parents: 68
diff changeset
244 {
kono
parents: 68
diff changeset
245 delete [] (fcache_tab);
kono
parents: 68
diff changeset
246 fcache_tab = NULL;
kono
parents: 68
diff changeset
247 }
kono
parents: 68
diff changeset
248 }
kono
parents: 68
diff changeset
249
kono
parents: 68
diff changeset
250 /* Return the total lines number that have been read so far by the
kono
parents: 68
diff changeset
251 line map (in the preprocessor) so far. For languages like C++ that
kono
parents: 68
diff changeset
252 entirely preprocess the input file before starting to parse, this
kono
parents: 68
diff changeset
253 equals the actual number of lines of the file. */
kono
parents: 68
diff changeset
254
kono
parents: 68
diff changeset
255 static size_t
kono
parents: 68
diff changeset
256 total_lines_num (const char *file_path)
kono
parents: 68
diff changeset
257 {
kono
parents: 68
diff changeset
258 size_t r = 0;
kono
parents: 68
diff changeset
259 source_location l = 0;
kono
parents: 68
diff changeset
260 if (linemap_get_file_highest_location (line_table, file_path, &l))
kono
parents: 68
diff changeset
261 {
kono
parents: 68
diff changeset
262 gcc_assert (l >= RESERVED_LOCATION_COUNT);
kono
parents: 68
diff changeset
263 expanded_location xloc = expand_location (l);
kono
parents: 68
diff changeset
264 r = xloc.line;
kono
parents: 68
diff changeset
265 }
kono
parents: 68
diff changeset
266 return r;
kono
parents: 68
diff changeset
267 }
kono
parents: 68
diff changeset
268
kono
parents: 68
diff changeset
269 /* Lookup the cache used for the content of a given file accessed by
kono
parents: 68
diff changeset
270 caret diagnostic. Return the found cached file, or NULL if no
kono
parents: 68
diff changeset
271 cached file was found. */
kono
parents: 68
diff changeset
272
kono
parents: 68
diff changeset
273 static fcache*
kono
parents: 68
diff changeset
274 lookup_file_in_cache_tab (const char *file_path)
kono
parents: 68
diff changeset
275 {
kono
parents: 68
diff changeset
276 if (file_path == NULL)
kono
parents: 68
diff changeset
277 return NULL;
kono
parents: 68
diff changeset
278
kono
parents: 68
diff changeset
279 diagnostic_file_cache_init ();
kono
parents: 68
diff changeset
280
kono
parents: 68
diff changeset
281 /* This will contain the found cached file. */
kono
parents: 68
diff changeset
282 fcache *r = NULL;
kono
parents: 68
diff changeset
283 for (unsigned i = 0; i < fcache_tab_size; ++i)
kono
parents: 68
diff changeset
284 {
kono
parents: 68
diff changeset
285 fcache *c = &fcache_tab[i];
kono
parents: 68
diff changeset
286 if (c->file_path && !strcmp (c->file_path, file_path))
kono
parents: 68
diff changeset
287 {
kono
parents: 68
diff changeset
288 ++c->use_count;
kono
parents: 68
diff changeset
289 r = c;
kono
parents: 68
diff changeset
290 }
kono
parents: 68
diff changeset
291 }
kono
parents: 68
diff changeset
292
kono
parents: 68
diff changeset
293 if (r)
kono
parents: 68
diff changeset
294 ++r->use_count;
kono
parents: 68
diff changeset
295
kono
parents: 68
diff changeset
296 return r;
kono
parents: 68
diff changeset
297 }
kono
parents: 68
diff changeset
298
kono
parents: 68
diff changeset
299 /* Purge any mention of FILENAME from the cache of files used for
kono
parents: 68
diff changeset
300 printing source code. For use in selftests when working
kono
parents: 68
diff changeset
301 with tempfiles. */
kono
parents: 68
diff changeset
302
kono
parents: 68
diff changeset
303 void
kono
parents: 68
diff changeset
304 diagnostics_file_cache_forcibly_evict_file (const char *file_path)
kono
parents: 68
diff changeset
305 {
kono
parents: 68
diff changeset
306 gcc_assert (file_path);
kono
parents: 68
diff changeset
307
kono
parents: 68
diff changeset
308 fcache *r = lookup_file_in_cache_tab (file_path);
kono
parents: 68
diff changeset
309 if (!r)
kono
parents: 68
diff changeset
310 /* Not found. */
kono
parents: 68
diff changeset
311 return;
kono
parents: 68
diff changeset
312
kono
parents: 68
diff changeset
313 r->file_path = NULL;
kono
parents: 68
diff changeset
314 if (r->fp)
kono
parents: 68
diff changeset
315 fclose (r->fp);
kono
parents: 68
diff changeset
316 r->fp = NULL;
kono
parents: 68
diff changeset
317 r->nb_read = 0;
kono
parents: 68
diff changeset
318 r->line_start_idx = 0;
kono
parents: 68
diff changeset
319 r->line_num = 0;
kono
parents: 68
diff changeset
320 r->line_record.truncate (0);
kono
parents: 68
diff changeset
321 r->use_count = 0;
kono
parents: 68
diff changeset
322 r->total_lines = 0;
kono
parents: 68
diff changeset
323 r->missing_trailing_newline = true;
kono
parents: 68
diff changeset
324 }
kono
parents: 68
diff changeset
325
kono
parents: 68
diff changeset
326 /* Return the file cache that has been less used, recently, or the
kono
parents: 68
diff changeset
327 first empty one. If HIGHEST_USE_COUNT is non-null,
kono
parents: 68
diff changeset
328 *HIGHEST_USE_COUNT is set to the highest use count of the entries
kono
parents: 68
diff changeset
329 in the cache table. */
kono
parents: 68
diff changeset
330
kono
parents: 68
diff changeset
331 static fcache*
kono
parents: 68
diff changeset
332 evicted_cache_tab_entry (unsigned *highest_use_count)
kono
parents: 68
diff changeset
333 {
kono
parents: 68
diff changeset
334 diagnostic_file_cache_init ();
kono
parents: 68
diff changeset
335
kono
parents: 68
diff changeset
336 fcache *to_evict = &fcache_tab[0];
kono
parents: 68
diff changeset
337 unsigned huc = to_evict->use_count;
kono
parents: 68
diff changeset
338 for (unsigned i = 1; i < fcache_tab_size; ++i)
kono
parents: 68
diff changeset
339 {
kono
parents: 68
diff changeset
340 fcache *c = &fcache_tab[i];
kono
parents: 68
diff changeset
341 bool c_is_empty = (c->file_path == NULL);
kono
parents: 68
diff changeset
342
kono
parents: 68
diff changeset
343 if (c->use_count < to_evict->use_count
kono
parents: 68
diff changeset
344 || (to_evict->file_path && c_is_empty))
kono
parents: 68
diff changeset
345 /* We evict C because it's either an entry with a lower use
kono
parents: 68
diff changeset
346 count or one that is empty. */
kono
parents: 68
diff changeset
347 to_evict = c;
kono
parents: 68
diff changeset
348
kono
parents: 68
diff changeset
349 if (huc < c->use_count)
kono
parents: 68
diff changeset
350 huc = c->use_count;
kono
parents: 68
diff changeset
351
kono
parents: 68
diff changeset
352 if (c_is_empty)
kono
parents: 68
diff changeset
353 /* We've reached the end of the cache; subsequent elements are
kono
parents: 68
diff changeset
354 all empty. */
kono
parents: 68
diff changeset
355 break;
kono
parents: 68
diff changeset
356 }
kono
parents: 68
diff changeset
357
kono
parents: 68
diff changeset
358 if (highest_use_count)
kono
parents: 68
diff changeset
359 *highest_use_count = huc;
kono
parents: 68
diff changeset
360
kono
parents: 68
diff changeset
361 return to_evict;
kono
parents: 68
diff changeset
362 }
kono
parents: 68
diff changeset
363
kono
parents: 68
diff changeset
364 /* Create the cache used for the content of a given file to be
kono
parents: 68
diff changeset
365 accessed by caret diagnostic. This cache is added to an array of
kono
parents: 68
diff changeset
366 cache and can be retrieved by lookup_file_in_cache_tab. This
kono
parents: 68
diff changeset
367 function returns the created cache. Note that only the last
kono
parents: 68
diff changeset
368 fcache_tab_size files are cached. */
kono
parents: 68
diff changeset
369
kono
parents: 68
diff changeset
370 static fcache*
kono
parents: 68
diff changeset
371 add_file_to_cache_tab (const char *file_path)
kono
parents: 68
diff changeset
372 {
kono
parents: 68
diff changeset
373
kono
parents: 68
diff changeset
374 FILE *fp = fopen (file_path, "r");
kono
parents: 68
diff changeset
375 if (fp == NULL)
kono
parents: 68
diff changeset
376 return NULL;
kono
parents: 68
diff changeset
377
kono
parents: 68
diff changeset
378 unsigned highest_use_count = 0;
kono
parents: 68
diff changeset
379 fcache *r = evicted_cache_tab_entry (&highest_use_count);
kono
parents: 68
diff changeset
380 r->file_path = file_path;
kono
parents: 68
diff changeset
381 if (r->fp)
kono
parents: 68
diff changeset
382 fclose (r->fp);
kono
parents: 68
diff changeset
383 r->fp = fp;
kono
parents: 68
diff changeset
384 r->nb_read = 0;
kono
parents: 68
diff changeset
385 r->line_start_idx = 0;
kono
parents: 68
diff changeset
386 r->line_num = 0;
kono
parents: 68
diff changeset
387 r->line_record.truncate (0);
kono
parents: 68
diff changeset
388 /* Ensure that this cache entry doesn't get evicted next time
kono
parents: 68
diff changeset
389 add_file_to_cache_tab is called. */
kono
parents: 68
diff changeset
390 r->use_count = ++highest_use_count;
kono
parents: 68
diff changeset
391 r->total_lines = total_lines_num (file_path);
kono
parents: 68
diff changeset
392 r->missing_trailing_newline = true;
kono
parents: 68
diff changeset
393
kono
parents: 68
diff changeset
394 return r;
kono
parents: 68
diff changeset
395 }
kono
parents: 68
diff changeset
396
kono
parents: 68
diff changeset
397 /* Lookup the cache used for the content of a given file accessed by
kono
parents: 68
diff changeset
398 caret diagnostic. If no cached file was found, create a new cache
kono
parents: 68
diff changeset
399 for this file, add it to the array of cached file and return
kono
parents: 68
diff changeset
400 it. */
kono
parents: 68
diff changeset
401
kono
parents: 68
diff changeset
402 static fcache*
kono
parents: 68
diff changeset
403 lookup_or_add_file_to_cache_tab (const char *file_path)
kono
parents: 68
diff changeset
404 {
kono
parents: 68
diff changeset
405 fcache *r = lookup_file_in_cache_tab (file_path);
kono
parents: 68
diff changeset
406 if (r == NULL)
kono
parents: 68
diff changeset
407 r = add_file_to_cache_tab (file_path);
kono
parents: 68
diff changeset
408 return r;
kono
parents: 68
diff changeset
409 }
kono
parents: 68
diff changeset
410
kono
parents: 68
diff changeset
411 /* Default constructor for a cache of file used by caret
kono
parents: 68
diff changeset
412 diagnostic. */
kono
parents: 68
diff changeset
413
kono
parents: 68
diff changeset
414 fcache::fcache ()
kono
parents: 68
diff changeset
415 : use_count (0), file_path (NULL), fp (NULL), data (0),
kono
parents: 68
diff changeset
416 size (0), nb_read (0), line_start_idx (0), line_num (0),
kono
parents: 68
diff changeset
417 total_lines (0), missing_trailing_newline (true)
kono
parents: 68
diff changeset
418 {
kono
parents: 68
diff changeset
419 line_record.create (0);
kono
parents: 68
diff changeset
420 }
kono
parents: 68
diff changeset
421
kono
parents: 68
diff changeset
422 /* Destructor for a cache of file used by caret diagnostic. */
kono
parents: 68
diff changeset
423
kono
parents: 68
diff changeset
424 fcache::~fcache ()
kono
parents: 68
diff changeset
425 {
kono
parents: 68
diff changeset
426 if (fp)
kono
parents: 68
diff changeset
427 {
kono
parents: 68
diff changeset
428 fclose (fp);
kono
parents: 68
diff changeset
429 fp = NULL;
kono
parents: 68
diff changeset
430 }
kono
parents: 68
diff changeset
431 if (data)
kono
parents: 68
diff changeset
432 {
kono
parents: 68
diff changeset
433 XDELETEVEC (data);
kono
parents: 68
diff changeset
434 data = 0;
kono
parents: 68
diff changeset
435 }
kono
parents: 68
diff changeset
436 line_record.release ();
kono
parents: 68
diff changeset
437 }
kono
parents: 68
diff changeset
438
kono
parents: 68
diff changeset
439 /* Returns TRUE iff the cache would need to be filled with data coming
kono
parents: 68
diff changeset
440 from the file. That is, either the cache is empty or full or the
kono
parents: 68
diff changeset
441 current line is empty. Note that if the cache is full, it would
kono
parents: 68
diff changeset
442 need to be extended and filled again. */
kono
parents: 68
diff changeset
443
kono
parents: 68
diff changeset
444 static bool
kono
parents: 68
diff changeset
445 needs_read (fcache *c)
kono
parents: 68
diff changeset
446 {
kono
parents: 68
diff changeset
447 return (c->nb_read == 0
kono
parents: 68
diff changeset
448 || c->nb_read == c->size
kono
parents: 68
diff changeset
449 || (c->line_start_idx >= c->nb_read - 1));
kono
parents: 68
diff changeset
450 }
kono
parents: 68
diff changeset
451
kono
parents: 68
diff changeset
452 /* Return TRUE iff the cache is full and thus needs to be
kono
parents: 68
diff changeset
453 extended. */
kono
parents: 68
diff changeset
454
kono
parents: 68
diff changeset
455 static bool
kono
parents: 68
diff changeset
456 needs_grow (fcache *c)
kono
parents: 68
diff changeset
457 {
kono
parents: 68
diff changeset
458 return c->nb_read == c->size;
kono
parents: 68
diff changeset
459 }
kono
parents: 68
diff changeset
460
kono
parents: 68
diff changeset
461 /* Grow the cache if it needs to be extended. */
kono
parents: 68
diff changeset
462
kono
parents: 68
diff changeset
463 static void
kono
parents: 68
diff changeset
464 maybe_grow (fcache *c)
kono
parents: 68
diff changeset
465 {
kono
parents: 68
diff changeset
466 if (!needs_grow (c))
kono
parents: 68
diff changeset
467 return;
kono
parents: 68
diff changeset
468
kono
parents: 68
diff changeset
469 size_t size = c->size == 0 ? fcache_buffer_size : c->size * 2;
kono
parents: 68
diff changeset
470 c->data = XRESIZEVEC (char, c->data, size);
kono
parents: 68
diff changeset
471 c->size = size;
kono
parents: 68
diff changeset
472 }
kono
parents: 68
diff changeset
473
kono
parents: 68
diff changeset
474 /* Read more data into the cache. Extends the cache if need be.
kono
parents: 68
diff changeset
475 Returns TRUE iff new data could be read. */
kono
parents: 68
diff changeset
476
kono
parents: 68
diff changeset
477 static bool
kono
parents: 68
diff changeset
478 read_data (fcache *c)
kono
parents: 68
diff changeset
479 {
kono
parents: 68
diff changeset
480 if (feof (c->fp) || ferror (c->fp))
kono
parents: 68
diff changeset
481 return false;
kono
parents: 68
diff changeset
482
kono
parents: 68
diff changeset
483 maybe_grow (c);
kono
parents: 68
diff changeset
484
kono
parents: 68
diff changeset
485 char * from = c->data + c->nb_read;
kono
parents: 68
diff changeset
486 size_t to_read = c->size - c->nb_read;
kono
parents: 68
diff changeset
487 size_t nb_read = fread (from, 1, to_read, c->fp);
kono
parents: 68
diff changeset
488
kono
parents: 68
diff changeset
489 if (ferror (c->fp))
kono
parents: 68
diff changeset
490 return false;
kono
parents: 68
diff changeset
491
kono
parents: 68
diff changeset
492 c->nb_read += nb_read;
kono
parents: 68
diff changeset
493 return !!nb_read;
kono
parents: 68
diff changeset
494 }
kono
parents: 68
diff changeset
495
kono
parents: 68
diff changeset
496 /* Read new data iff the cache needs to be filled with more data
kono
parents: 68
diff changeset
497 coming from the file FP. Return TRUE iff the cache was filled with
kono
parents: 68
diff changeset
498 mode data. */
kono
parents: 68
diff changeset
499
kono
parents: 68
diff changeset
500 static bool
kono
parents: 68
diff changeset
501 maybe_read_data (fcache *c)
kono
parents: 68
diff changeset
502 {
kono
parents: 68
diff changeset
503 if (!needs_read (c))
kono
parents: 68
diff changeset
504 return false;
kono
parents: 68
diff changeset
505 return read_data (c);
kono
parents: 68
diff changeset
506 }
kono
parents: 68
diff changeset
507
kono
parents: 68
diff changeset
508 /* Read a new line from file FP, using C as a cache for the data
kono
parents: 68
diff changeset
509 coming from the file. Upon successful completion, *LINE is set to
kono
parents: 68
diff changeset
510 the beginning of the line found. *LINE points directly in the
kono
parents: 68
diff changeset
511 line cache and is only valid until the next call of get_next_line.
kono
parents: 68
diff changeset
512 *LINE_LEN is set to the length of the line. Note that the line
kono
parents: 68
diff changeset
513 does not contain any terminal delimiter. This function returns
kono
parents: 68
diff changeset
514 true if some data was read or process from the cache, false
kono
parents: 68
diff changeset
515 otherwise. Note that subsequent calls to get_next_line might
kono
parents: 68
diff changeset
516 make the content of *LINE invalid. */
kono
parents: 68
diff changeset
517
kono
parents: 68
diff changeset
518 static bool
kono
parents: 68
diff changeset
519 get_next_line (fcache *c, char **line, ssize_t *line_len)
kono
parents: 68
diff changeset
520 {
kono
parents: 68
diff changeset
521 /* Fill the cache with data to process. */
kono
parents: 68
diff changeset
522 maybe_read_data (c);
kono
parents: 68
diff changeset
523
kono
parents: 68
diff changeset
524 size_t remaining_size = c->nb_read - c->line_start_idx;
kono
parents: 68
diff changeset
525 if (remaining_size == 0)
kono
parents: 68
diff changeset
526 /* There is no more data to process. */
kono
parents: 68
diff changeset
527 return false;
kono
parents: 68
diff changeset
528
kono
parents: 68
diff changeset
529 char *line_start = c->data + c->line_start_idx;
kono
parents: 68
diff changeset
530
kono
parents: 68
diff changeset
531 char *next_line_start = NULL;
kono
parents: 68
diff changeset
532 size_t len = 0;
kono
parents: 68
diff changeset
533 char *line_end = (char *) memchr (line_start, '\n', remaining_size);
kono
parents: 68
diff changeset
534 if (line_end == NULL)
kono
parents: 68
diff changeset
535 {
kono
parents: 68
diff changeset
536 /* We haven't found the end-of-line delimiter in the cache.
kono
parents: 68
diff changeset
537 Fill the cache with more data from the file and look for the
kono
parents: 68
diff changeset
538 '\n'. */
kono
parents: 68
diff changeset
539 while (maybe_read_data (c))
kono
parents: 68
diff changeset
540 {
kono
parents: 68
diff changeset
541 line_start = c->data + c->line_start_idx;
kono
parents: 68
diff changeset
542 remaining_size = c->nb_read - c->line_start_idx;
kono
parents: 68
diff changeset
543 line_end = (char *) memchr (line_start, '\n', remaining_size);
kono
parents: 68
diff changeset
544 if (line_end != NULL)
kono
parents: 68
diff changeset
545 {
kono
parents: 68
diff changeset
546 next_line_start = line_end + 1;
kono
parents: 68
diff changeset
547 break;
kono
parents: 68
diff changeset
548 }
kono
parents: 68
diff changeset
549 }
kono
parents: 68
diff changeset
550 if (line_end == NULL)
kono
parents: 68
diff changeset
551 {
kono
parents: 68
diff changeset
552 /* We've loadded all the file into the cache and still no
kono
parents: 68
diff changeset
553 '\n'. Let's say the line ends up at one byte passed the
kono
parents: 68
diff changeset
554 end of the file. This is to stay consistent with the case
kono
parents: 68
diff changeset
555 of when the line ends up with a '\n' and line_end points to
kono
parents: 68
diff changeset
556 that terminal '\n'. That consistency is useful below in
kono
parents: 68
diff changeset
557 the len calculation. */
kono
parents: 68
diff changeset
558 line_end = c->data + c->nb_read ;
kono
parents: 68
diff changeset
559 c->missing_trailing_newline = true;
kono
parents: 68
diff changeset
560 }
kono
parents: 68
diff changeset
561 else
kono
parents: 68
diff changeset
562 c->missing_trailing_newline = false;
kono
parents: 68
diff changeset
563 }
kono
parents: 68
diff changeset
564 else
kono
parents: 68
diff changeset
565 {
kono
parents: 68
diff changeset
566 next_line_start = line_end + 1;
kono
parents: 68
diff changeset
567 c->missing_trailing_newline = false;
kono
parents: 68
diff changeset
568 }
kono
parents: 68
diff changeset
569
kono
parents: 68
diff changeset
570 if (ferror (c->fp))
kono
parents: 68
diff changeset
571 return false;
kono
parents: 68
diff changeset
572
kono
parents: 68
diff changeset
573 /* At this point, we've found the end of the of line. It either
kono
parents: 68
diff changeset
574 points to the '\n' or to one byte after the last byte of the
kono
parents: 68
diff changeset
575 file. */
kono
parents: 68
diff changeset
576 gcc_assert (line_end != NULL);
kono
parents: 68
diff changeset
577
kono
parents: 68
diff changeset
578 len = line_end - line_start;
kono
parents: 68
diff changeset
579
kono
parents: 68
diff changeset
580 if (c->line_start_idx < c->nb_read)
kono
parents: 68
diff changeset
581 *line = line_start;
kono
parents: 68
diff changeset
582
kono
parents: 68
diff changeset
583 ++c->line_num;
kono
parents: 68
diff changeset
584
kono
parents: 68
diff changeset
585 /* Before we update our line record, make sure the hint about the
kono
parents: 68
diff changeset
586 total number of lines of the file is correct. If it's not, then
kono
parents: 68
diff changeset
587 we give up recording line boundaries from now on. */
kono
parents: 68
diff changeset
588 bool update_line_record = true;
kono
parents: 68
diff changeset
589 if (c->line_num > c->total_lines)
kono
parents: 68
diff changeset
590 update_line_record = false;
kono
parents: 68
diff changeset
591
kono
parents: 68
diff changeset
592 /* Now update our line record so that re-reading lines from the
kono
parents: 68
diff changeset
593 before c->line_start_idx is faster. */
kono
parents: 68
diff changeset
594 if (update_line_record
kono
parents: 68
diff changeset
595 && c->line_record.length () < fcache_line_record_size)
kono
parents: 68
diff changeset
596 {
kono
parents: 68
diff changeset
597 /* If the file lines fits in the line record, we just record all
kono
parents: 68
diff changeset
598 its lines ...*/
kono
parents: 68
diff changeset
599 if (c->total_lines <= fcache_line_record_size
kono
parents: 68
diff changeset
600 && c->line_num > c->line_record.length ())
kono
parents: 68
diff changeset
601 c->line_record.safe_push (fcache::line_info (c->line_num,
kono
parents: 68
diff changeset
602 c->line_start_idx,
kono
parents: 68
diff changeset
603 line_end - c->data));
kono
parents: 68
diff changeset
604 else if (c->total_lines > fcache_line_record_size)
kono
parents: 68
diff changeset
605 {
kono
parents: 68
diff changeset
606 /* ... otherwise, we just scale total_lines down to
kono
parents: 68
diff changeset
607 (fcache_line_record_size lines. */
kono
parents: 68
diff changeset
608 size_t n = (c->line_num * fcache_line_record_size) / c->total_lines;
kono
parents: 68
diff changeset
609 if (c->line_record.length () == 0
kono
parents: 68
diff changeset
610 || n >= c->line_record.length ())
kono
parents: 68
diff changeset
611 c->line_record.safe_push (fcache::line_info (c->line_num,
kono
parents: 68
diff changeset
612 c->line_start_idx,
kono
parents: 68
diff changeset
613 line_end - c->data));
kono
parents: 68
diff changeset
614 }
kono
parents: 68
diff changeset
615 }
kono
parents: 68
diff changeset
616
kono
parents: 68
diff changeset
617 /* Update c->line_start_idx so that it points to the next line to be
kono
parents: 68
diff changeset
618 read. */
kono
parents: 68
diff changeset
619 if (next_line_start)
kono
parents: 68
diff changeset
620 c->line_start_idx = next_line_start - c->data;
kono
parents: 68
diff changeset
621 else
kono
parents: 68
diff changeset
622 /* We didn't find any terminal '\n'. Let's consider that the end
kono
parents: 68
diff changeset
623 of line is the end of the data in the cache. The next
kono
parents: 68
diff changeset
624 invocation of get_next_line will either read more data from the
kono
parents: 68
diff changeset
625 underlying file or return false early because we've reached the
kono
parents: 68
diff changeset
626 end of the file. */
kono
parents: 68
diff changeset
627 c->line_start_idx = c->nb_read;
kono
parents: 68
diff changeset
628
kono
parents: 68
diff changeset
629 *line_len = len;
kono
parents: 68
diff changeset
630
kono
parents: 68
diff changeset
631 return true;
kono
parents: 68
diff changeset
632 }
kono
parents: 68
diff changeset
633
kono
parents: 68
diff changeset
634 /* Consume the next bytes coming from the cache (or from its
kono
parents: 68
diff changeset
635 underlying file if there are remaining unread bytes in the file)
kono
parents: 68
diff changeset
636 until we reach the next end-of-line (or end-of-file). There is no
kono
parents: 68
diff changeset
637 copying from the cache involved. Return TRUE upon successful
kono
parents: 68
diff changeset
638 completion. */
kono
parents: 68
diff changeset
639
kono
parents: 68
diff changeset
640 static bool
kono
parents: 68
diff changeset
641 goto_next_line (fcache *cache)
kono
parents: 68
diff changeset
642 {
kono
parents: 68
diff changeset
643 char *l;
kono
parents: 68
diff changeset
644 ssize_t len;
kono
parents: 68
diff changeset
645
kono
parents: 68
diff changeset
646 return get_next_line (cache, &l, &len);
kono
parents: 68
diff changeset
647 }
kono
parents: 68
diff changeset
648
kono
parents: 68
diff changeset
649 /* Read an arbitrary line number LINE_NUM from the file cached in C.
kono
parents: 68
diff changeset
650 If the line was read successfully, *LINE points to the beginning
kono
parents: 68
diff changeset
651 of the line in the file cache and *LINE_LEN is the length of the
kono
parents: 68
diff changeset
652 line. *LINE is not nul-terminated, but may contain zero bytes.
kono
parents: 68
diff changeset
653 *LINE is only valid until the next call of read_line_num.
kono
parents: 68
diff changeset
654 This function returns bool if a line was read. */
kono
parents: 68
diff changeset
655
kono
parents: 68
diff changeset
656 static bool
kono
parents: 68
diff changeset
657 read_line_num (fcache *c, size_t line_num,
kono
parents: 68
diff changeset
658 char **line, ssize_t *line_len)
kono
parents: 68
diff changeset
659 {
kono
parents: 68
diff changeset
660 gcc_assert (line_num > 0);
kono
parents: 68
diff changeset
661
kono
parents: 68
diff changeset
662 if (line_num <= c->line_num)
kono
parents: 68
diff changeset
663 {
kono
parents: 68
diff changeset
664 /* We've been asked to read lines that are before c->line_num.
kono
parents: 68
diff changeset
665 So lets use our line record (if it's not empty) to try to
kono
parents: 68
diff changeset
666 avoid re-reading the file from the beginning again. */
kono
parents: 68
diff changeset
667
kono
parents: 68
diff changeset
668 if (c->line_record.is_empty ())
kono
parents: 68
diff changeset
669 {
kono
parents: 68
diff changeset
670 c->line_start_idx = 0;
kono
parents: 68
diff changeset
671 c->line_num = 0;
kono
parents: 68
diff changeset
672 }
kono
parents: 68
diff changeset
673 else
kono
parents: 68
diff changeset
674 {
kono
parents: 68
diff changeset
675 fcache::line_info *i = NULL;
kono
parents: 68
diff changeset
676 if (c->total_lines <= fcache_line_record_size)
kono
parents: 68
diff changeset
677 {
kono
parents: 68
diff changeset
678 /* In languages where the input file is not totally
kono
parents: 68
diff changeset
679 preprocessed up front, the c->total_lines hint
kono
parents: 68
diff changeset
680 can be smaller than the number of lines of the
kono
parents: 68
diff changeset
681 file. In that case, only the first
kono
parents: 68
diff changeset
682 c->total_lines have been recorded.
kono
parents: 68
diff changeset
683
kono
parents: 68
diff changeset
684 Otherwise, the first c->total_lines we've read have
kono
parents: 68
diff changeset
685 their start/end recorded here. */
kono
parents: 68
diff changeset
686 i = (line_num <= c->total_lines)
kono
parents: 68
diff changeset
687 ? &c->line_record[line_num - 1]
kono
parents: 68
diff changeset
688 : &c->line_record[c->total_lines - 1];
kono
parents: 68
diff changeset
689 gcc_assert (i->line_num <= line_num);
kono
parents: 68
diff changeset
690 }
kono
parents: 68
diff changeset
691 else
kono
parents: 68
diff changeset
692 {
kono
parents: 68
diff changeset
693 /* So the file had more lines than our line record
kono
parents: 68
diff changeset
694 size. Thus the number of lines we've recorded has
kono
parents: 68
diff changeset
695 been scaled down to fcache_line_reacord_size. Let's
kono
parents: 68
diff changeset
696 pick the start/end of the recorded line that is
kono
parents: 68
diff changeset
697 closest to line_num. */
kono
parents: 68
diff changeset
698 size_t n = (line_num <= c->total_lines)
kono
parents: 68
diff changeset
699 ? line_num * fcache_line_record_size / c->total_lines
kono
parents: 68
diff changeset
700 : c ->line_record.length () - 1;
kono
parents: 68
diff changeset
701 if (n < c->line_record.length ())
kono
parents: 68
diff changeset
702 {
kono
parents: 68
diff changeset
703 i = &c->line_record[n];
kono
parents: 68
diff changeset
704 gcc_assert (i->line_num <= line_num);
kono
parents: 68
diff changeset
705 }
kono
parents: 68
diff changeset
706 }
kono
parents: 68
diff changeset
707
kono
parents: 68
diff changeset
708 if (i && i->line_num == line_num)
kono
parents: 68
diff changeset
709 {
kono
parents: 68
diff changeset
710 /* We have the start/end of the line. */
kono
parents: 68
diff changeset
711 *line = c->data + i->start_pos;
kono
parents: 68
diff changeset
712 *line_len = i->end_pos - i->start_pos;
kono
parents: 68
diff changeset
713 return true;
kono
parents: 68
diff changeset
714 }
kono
parents: 68
diff changeset
715
kono
parents: 68
diff changeset
716 if (i)
kono
parents: 68
diff changeset
717 {
kono
parents: 68
diff changeset
718 c->line_start_idx = i->start_pos;
kono
parents: 68
diff changeset
719 c->line_num = i->line_num - 1;
kono
parents: 68
diff changeset
720 }
kono
parents: 68
diff changeset
721 else
kono
parents: 68
diff changeset
722 {
kono
parents: 68
diff changeset
723 c->line_start_idx = 0;
kono
parents: 68
diff changeset
724 c->line_num = 0;
kono
parents: 68
diff changeset
725 }
kono
parents: 68
diff changeset
726 }
kono
parents: 68
diff changeset
727 }
kono
parents: 68
diff changeset
728
kono
parents: 68
diff changeset
729 /* Let's walk from line c->line_num up to line_num - 1, without
kono
parents: 68
diff changeset
730 copying any line. */
kono
parents: 68
diff changeset
731 while (c->line_num < line_num - 1)
kono
parents: 68
diff changeset
732 if (!goto_next_line (c))
kono
parents: 68
diff changeset
733 return false;
kono
parents: 68
diff changeset
734
kono
parents: 68
diff changeset
735 /* The line we want is the next one. Let's read and copy it back to
kono
parents: 68
diff changeset
736 the caller. */
kono
parents: 68
diff changeset
737 return get_next_line (c, line, line_len);
kono
parents: 68
diff changeset
738 }
kono
parents: 68
diff changeset
739
kono
parents: 68
diff changeset
740 /* Return the physical source line that corresponds to FILE_PATH/LINE.
kono
parents: 68
diff changeset
741 The line is not nul-terminated. The returned pointer is only
kono
parents: 68
diff changeset
742 valid until the next call of location_get_source_line.
kono
parents: 68
diff changeset
743 Note that the line can contain several null characters,
kono
parents: 68
diff changeset
744 so LINE_LEN, if non-null, points to the actual length of the line.
kono
parents: 68
diff changeset
745 If the function fails, NULL is returned. */
kono
parents: 68
diff changeset
746
kono
parents: 68
diff changeset
747 const char *
kono
parents: 68
diff changeset
748 location_get_source_line (const char *file_path, int line,
kono
parents: 68
diff changeset
749 int *line_len)
kono
parents: 68
diff changeset
750 {
kono
parents: 68
diff changeset
751 char *buffer = NULL;
kono
parents: 68
diff changeset
752 ssize_t len;
kono
parents: 68
diff changeset
753
kono
parents: 68
diff changeset
754 if (line == 0)
kono
parents: 68
diff changeset
755 return NULL;
kono
parents: 68
diff changeset
756
kono
parents: 68
diff changeset
757 fcache *c = lookup_or_add_file_to_cache_tab (file_path);
kono
parents: 68
diff changeset
758 if (c == NULL)
kono
parents: 68
diff changeset
759 return NULL;
kono
parents: 68
diff changeset
760
kono
parents: 68
diff changeset
761 bool read = read_line_num (c, line, &buffer, &len);
kono
parents: 68
diff changeset
762
kono
parents: 68
diff changeset
763 if (read && line_len)
kono
parents: 68
diff changeset
764 *line_len = len;
kono
parents: 68
diff changeset
765
kono
parents: 68
diff changeset
766 return read ? buffer : NULL;
kono
parents: 68
diff changeset
767 }
kono
parents: 68
diff changeset
768
kono
parents: 68
diff changeset
769 /* Determine if FILE_PATH missing a trailing newline on its final line.
kono
parents: 68
diff changeset
770 Only valid to call once all of the file has been loaded, by
kono
parents: 68
diff changeset
771 requesting a line number beyond the end of the file. */
kono
parents: 68
diff changeset
772
kono
parents: 68
diff changeset
773 bool
kono
parents: 68
diff changeset
774 location_missing_trailing_newline (const char *file_path)
kono
parents: 68
diff changeset
775 {
kono
parents: 68
diff changeset
776 fcache *c = lookup_or_add_file_to_cache_tab (file_path);
kono
parents: 68
diff changeset
777 if (c == NULL)
kono
parents: 68
diff changeset
778 return false;
kono
parents: 68
diff changeset
779
kono
parents: 68
diff changeset
780 return c->missing_trailing_newline;
kono
parents: 68
diff changeset
781 }
kono
parents: 68
diff changeset
782
kono
parents: 68
diff changeset
783 /* Test if the location originates from the spelling location of a
kono
parents: 68
diff changeset
784 builtin-tokens. That is, return TRUE if LOC is a (possibly
kono
parents: 68
diff changeset
785 virtual) location of a built-in token that appears in the expansion
kono
parents: 68
diff changeset
786 list of a macro. Please note that this function also works on
kono
parents: 68
diff changeset
787 tokens that result from built-in tokens. For instance, the
kono
parents: 68
diff changeset
788 function would return true if passed a token "4" that is the result
kono
parents: 68
diff changeset
789 of the expansion of the built-in __LINE__ macro. */
kono
parents: 68
diff changeset
790 bool
kono
parents: 68
diff changeset
791 is_location_from_builtin_token (source_location loc)
kono
parents: 68
diff changeset
792 {
kono
parents: 68
diff changeset
793 const line_map_ordinary *map = NULL;
kono
parents: 68
diff changeset
794 loc = linemap_resolve_location (line_table, loc,
kono
parents: 68
diff changeset
795 LRK_SPELLING_LOCATION, &map);
kono
parents: 68
diff changeset
796 return loc == BUILTINS_LOCATION;
kono
parents: 68
diff changeset
797 }
kono
parents: 68
diff changeset
798
kono
parents: 68
diff changeset
799 /* Expand the source location LOC into a human readable location. If
kono
parents: 68
diff changeset
800 LOC is virtual, it resolves to the expansion point of the involved
kono
parents: 68
diff changeset
801 macro. If LOC resolves to a builtin location, the file name of the
kono
parents: 68
diff changeset
802 readable location is set to the string "<built-in>". */
kono
parents: 68
diff changeset
803
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
804 expanded_location
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
805 expand_location (source_location loc)
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
806 {
111
kono
parents: 68
diff changeset
807 return expand_location_1 (loc, /*expansion_point_p=*/true,
kono
parents: 68
diff changeset
808 LOCATION_ASPECT_CARET);
kono
parents: 68
diff changeset
809 }
kono
parents: 68
diff changeset
810
kono
parents: 68
diff changeset
811 /* Expand the source location LOC into a human readable location. If
kono
parents: 68
diff changeset
812 LOC is virtual, it resolves to the expansion location of the
kono
parents: 68
diff changeset
813 relevant macro. If LOC resolves to a builtin location, the file
kono
parents: 68
diff changeset
814 name of the readable location is set to the string
kono
parents: 68
diff changeset
815 "<built-in>". */
kono
parents: 68
diff changeset
816
kono
parents: 68
diff changeset
817 expanded_location
kono
parents: 68
diff changeset
818 expand_location_to_spelling_point (source_location loc)
kono
parents: 68
diff changeset
819 {
kono
parents: 68
diff changeset
820 return expand_location_1 (loc, /*expansion_point_p=*/false,
kono
parents: 68
diff changeset
821 LOCATION_ASPECT_CARET);
kono
parents: 68
diff changeset
822 }
kono
parents: 68
diff changeset
823
kono
parents: 68
diff changeset
824 /* The rich_location class within libcpp requires a way to expand
kono
parents: 68
diff changeset
825 source_location instances, and relies on the client code
kono
parents: 68
diff changeset
826 providing a symbol named
kono
parents: 68
diff changeset
827 linemap_client_expand_location_to_spelling_point
kono
parents: 68
diff changeset
828 to do this.
kono
parents: 68
diff changeset
829
kono
parents: 68
diff changeset
830 This is the implementation for libcommon.a (all host binaries),
kono
parents: 68
diff changeset
831 which simply calls into expand_location_1. */
kono
parents: 68
diff changeset
832
kono
parents: 68
diff changeset
833 expanded_location
kono
parents: 68
diff changeset
834 linemap_client_expand_location_to_spelling_point (source_location loc,
kono
parents: 68
diff changeset
835 enum location_aspect aspect)
kono
parents: 68
diff changeset
836 {
kono
parents: 68
diff changeset
837 return expand_location_1 (loc, /*expansion_point_p=*/false, aspect);
kono
parents: 68
diff changeset
838 }
kono
parents: 68
diff changeset
839
kono
parents: 68
diff changeset
840
kono
parents: 68
diff changeset
841 /* If LOCATION is in a system header and if it is a virtual location for
kono
parents: 68
diff changeset
842 a token coming from the expansion of a macro, unwind it to the
kono
parents: 68
diff changeset
843 location of the expansion point of the macro. Otherwise, just return
kono
parents: 68
diff changeset
844 LOCATION.
kono
parents: 68
diff changeset
845
kono
parents: 68
diff changeset
846 This is used for instance when we want to emit diagnostics about a
kono
parents: 68
diff changeset
847 token that may be located in a macro that is itself defined in a
kono
parents: 68
diff changeset
848 system header, for example, for the NULL macro. In such a case, if
kono
parents: 68
diff changeset
849 LOCATION were passed directly to diagnostic functions such as
kono
parents: 68
diff changeset
850 warning_at, the diagnostic would be suppressed (unless
kono
parents: 68
diff changeset
851 -Wsystem-headers). */
kono
parents: 68
diff changeset
852
kono
parents: 68
diff changeset
853 source_location
kono
parents: 68
diff changeset
854 expansion_point_location_if_in_system_header (source_location location)
kono
parents: 68
diff changeset
855 {
kono
parents: 68
diff changeset
856 if (in_system_header_at (location))
kono
parents: 68
diff changeset
857 location = linemap_resolve_location (line_table, location,
kono
parents: 68
diff changeset
858 LRK_MACRO_EXPANSION_POINT,
kono
parents: 68
diff changeset
859 NULL);
kono
parents: 68
diff changeset
860 return location;
kono
parents: 68
diff changeset
861 }
kono
parents: 68
diff changeset
862
kono
parents: 68
diff changeset
863 /* If LOCATION is a virtual location for a token coming from the expansion
kono
parents: 68
diff changeset
864 of a macro, unwind to the location of the expansion point of the macro. */
kono
parents: 68
diff changeset
865
kono
parents: 68
diff changeset
866 source_location
kono
parents: 68
diff changeset
867 expansion_point_location (source_location location)
kono
parents: 68
diff changeset
868 {
kono
parents: 68
diff changeset
869 return linemap_resolve_location (line_table, location,
kono
parents: 68
diff changeset
870 LRK_MACRO_EXPANSION_POINT, NULL);
kono
parents: 68
diff changeset
871 }
kono
parents: 68
diff changeset
872
kono
parents: 68
diff changeset
873 /* Construct a location with caret at CARET, ranging from START to
kono
parents: 68
diff changeset
874 finish e.g.
kono
parents: 68
diff changeset
875
kono
parents: 68
diff changeset
876 11111111112
kono
parents: 68
diff changeset
877 12345678901234567890
kono
parents: 68
diff changeset
878 522
kono
parents: 68
diff changeset
879 523 return foo + bar;
kono
parents: 68
diff changeset
880 ~~~~^~~~~
kono
parents: 68
diff changeset
881 524
kono
parents: 68
diff changeset
882
kono
parents: 68
diff changeset
883 The location's caret is at the "+", line 523 column 15, but starts
kono
parents: 68
diff changeset
884 earlier, at the "f" of "foo" at column 11. The finish is at the "r"
kono
parents: 68
diff changeset
885 of "bar" at column 19. */
kono
parents: 68
diff changeset
886
kono
parents: 68
diff changeset
887 location_t
kono
parents: 68
diff changeset
888 make_location (location_t caret, location_t start, location_t finish)
kono
parents: 68
diff changeset
889 {
kono
parents: 68
diff changeset
890 location_t pure_loc = get_pure_location (caret);
kono
parents: 68
diff changeset
891 source_range src_range;
kono
parents: 68
diff changeset
892 src_range.m_start = get_start (start);
kono
parents: 68
diff changeset
893 src_range.m_finish = get_finish (finish);
kono
parents: 68
diff changeset
894 location_t combined_loc = COMBINE_LOCATION_DATA (line_table,
kono
parents: 68
diff changeset
895 pure_loc,
kono
parents: 68
diff changeset
896 src_range,
kono
parents: 68
diff changeset
897 NULL);
kono
parents: 68
diff changeset
898 return combined_loc;
kono
parents: 68
diff changeset
899 }
kono
parents: 68
diff changeset
900
kono
parents: 68
diff changeset
901 /* Same as above, but taking a source range rather than two locations. */
kono
parents: 68
diff changeset
902
kono
parents: 68
diff changeset
903 location_t
kono
parents: 68
diff changeset
904 make_location (location_t caret, source_range src_range)
kono
parents: 68
diff changeset
905 {
kono
parents: 68
diff changeset
906 location_t pure_loc = get_pure_location (caret);
kono
parents: 68
diff changeset
907 return COMBINE_LOCATION_DATA (line_table, pure_loc, src_range, NULL);
kono
parents: 68
diff changeset
908 }
kono
parents: 68
diff changeset
909
kono
parents: 68
diff changeset
910 #define ONE_K 1024
kono
parents: 68
diff changeset
911 #define ONE_M (ONE_K * ONE_K)
kono
parents: 68
diff changeset
912
kono
parents: 68
diff changeset
913 /* Display a number as an integer multiple of either:
kono
parents: 68
diff changeset
914 - 1024, if said integer is >= to 10 K (in base 2)
kono
parents: 68
diff changeset
915 - 1024 * 1024, if said integer is >= 10 M in (base 2)
kono
parents: 68
diff changeset
916 */
kono
parents: 68
diff changeset
917 #define SCALE(x) ((unsigned long) ((x) < 10 * ONE_K \
kono
parents: 68
diff changeset
918 ? (x) \
kono
parents: 68
diff changeset
919 : ((x) < 10 * ONE_M \
kono
parents: 68
diff changeset
920 ? (x) / ONE_K \
kono
parents: 68
diff changeset
921 : (x) / ONE_M)))
kono
parents: 68
diff changeset
922
kono
parents: 68
diff changeset
923 /* For a given integer, display either:
kono
parents: 68
diff changeset
924 - the character 'k', if the number is higher than 10 K (in base 2)
kono
parents: 68
diff changeset
925 but strictly lower than 10 M (in base 2)
kono
parents: 68
diff changeset
926 - the character 'M' if the number is higher than 10 M (in base2)
kono
parents: 68
diff changeset
927 - the charcter ' ' if the number is strictly lower than 10 K */
kono
parents: 68
diff changeset
928 #define STAT_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
kono
parents: 68
diff changeset
929
kono
parents: 68
diff changeset
930 /* Display an integer amount as multiple of 1K or 1M (in base 2).
kono
parents: 68
diff changeset
931 Display the correct unit (either k, M, or ' ') after the amount, as
kono
parents: 68
diff changeset
932 well. */
kono
parents: 68
diff changeset
933 #define FORMAT_AMOUNT(size) SCALE (size), STAT_LABEL (size)
kono
parents: 68
diff changeset
934
kono
parents: 68
diff changeset
935 /* Dump statistics to stderr about the memory usage of the line_table
kono
parents: 68
diff changeset
936 set of line maps. This also displays some statistics about macro
kono
parents: 68
diff changeset
937 expansion. */
kono
parents: 68
diff changeset
938
kono
parents: 68
diff changeset
939 void
kono
parents: 68
diff changeset
940 dump_line_table_statistics (void)
kono
parents: 68
diff changeset
941 {
kono
parents: 68
diff changeset
942 struct linemap_stats s;
kono
parents: 68
diff changeset
943 long total_used_map_size,
kono
parents: 68
diff changeset
944 macro_maps_size,
kono
parents: 68
diff changeset
945 total_allocated_map_size;
kono
parents: 68
diff changeset
946
kono
parents: 68
diff changeset
947 memset (&s, 0, sizeof (s));
kono
parents: 68
diff changeset
948
kono
parents: 68
diff changeset
949 linemap_get_statistics (line_table, &s);
kono
parents: 68
diff changeset
950
kono
parents: 68
diff changeset
951 macro_maps_size = s.macro_maps_used_size
kono
parents: 68
diff changeset
952 + s.macro_maps_locations_size;
kono
parents: 68
diff changeset
953
kono
parents: 68
diff changeset
954 total_allocated_map_size = s.ordinary_maps_allocated_size
kono
parents: 68
diff changeset
955 + s.macro_maps_allocated_size
kono
parents: 68
diff changeset
956 + s.macro_maps_locations_size;
kono
parents: 68
diff changeset
957
kono
parents: 68
diff changeset
958 total_used_map_size = s.ordinary_maps_used_size
kono
parents: 68
diff changeset
959 + s.macro_maps_used_size
kono
parents: 68
diff changeset
960 + s.macro_maps_locations_size;
kono
parents: 68
diff changeset
961
kono
parents: 68
diff changeset
962 fprintf (stderr, "Number of expanded macros: %5ld\n",
kono
parents: 68
diff changeset
963 s.num_expanded_macros);
kono
parents: 68
diff changeset
964 if (s.num_expanded_macros != 0)
kono
parents: 68
diff changeset
965 fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
kono
parents: 68
diff changeset
966 s.num_macro_tokens / s.num_expanded_macros);
kono
parents: 68
diff changeset
967 fprintf (stderr,
kono
parents: 68
diff changeset
968 "\nLine Table allocations during the "
kono
parents: 68
diff changeset
969 "compilation process\n");
kono
parents: 68
diff changeset
970 fprintf (stderr, "Number of ordinary maps used: %5ld%c\n",
kono
parents: 68
diff changeset
971 SCALE (s.num_ordinary_maps_used),
kono
parents: 68
diff changeset
972 STAT_LABEL (s.num_ordinary_maps_used));
kono
parents: 68
diff changeset
973 fprintf (stderr, "Ordinary map used size: %5ld%c\n",
kono
parents: 68
diff changeset
974 SCALE (s.ordinary_maps_used_size),
kono
parents: 68
diff changeset
975 STAT_LABEL (s.ordinary_maps_used_size));
kono
parents: 68
diff changeset
976 fprintf (stderr, "Number of ordinary maps allocated: %5ld%c\n",
kono
parents: 68
diff changeset
977 SCALE (s.num_ordinary_maps_allocated),
kono
parents: 68
diff changeset
978 STAT_LABEL (s.num_ordinary_maps_allocated));
kono
parents: 68
diff changeset
979 fprintf (stderr, "Ordinary maps allocated size: %5ld%c\n",
kono
parents: 68
diff changeset
980 SCALE (s.ordinary_maps_allocated_size),
kono
parents: 68
diff changeset
981 STAT_LABEL (s.ordinary_maps_allocated_size));
kono
parents: 68
diff changeset
982 fprintf (stderr, "Number of macro maps used: %5ld%c\n",
kono
parents: 68
diff changeset
983 SCALE (s.num_macro_maps_used),
kono
parents: 68
diff changeset
984 STAT_LABEL (s.num_macro_maps_used));
kono
parents: 68
diff changeset
985 fprintf (stderr, "Macro maps used size: %5ld%c\n",
kono
parents: 68
diff changeset
986 SCALE (s.macro_maps_used_size),
kono
parents: 68
diff changeset
987 STAT_LABEL (s.macro_maps_used_size));
kono
parents: 68
diff changeset
988 fprintf (stderr, "Macro maps locations size: %5ld%c\n",
kono
parents: 68
diff changeset
989 SCALE (s.macro_maps_locations_size),
kono
parents: 68
diff changeset
990 STAT_LABEL (s.macro_maps_locations_size));
kono
parents: 68
diff changeset
991 fprintf (stderr, "Macro maps size: %5ld%c\n",
kono
parents: 68
diff changeset
992 SCALE (macro_maps_size),
kono
parents: 68
diff changeset
993 STAT_LABEL (macro_maps_size));
kono
parents: 68
diff changeset
994 fprintf (stderr, "Duplicated maps locations size: %5ld%c\n",
kono
parents: 68
diff changeset
995 SCALE (s.duplicated_macro_maps_locations_size),
kono
parents: 68
diff changeset
996 STAT_LABEL (s.duplicated_macro_maps_locations_size));
kono
parents: 68
diff changeset
997 fprintf (stderr, "Total allocated maps size: %5ld%c\n",
kono
parents: 68
diff changeset
998 SCALE (total_allocated_map_size),
kono
parents: 68
diff changeset
999 STAT_LABEL (total_allocated_map_size));
kono
parents: 68
diff changeset
1000 fprintf (stderr, "Total used maps size: %5ld%c\n",
kono
parents: 68
diff changeset
1001 SCALE (total_used_map_size),
kono
parents: 68
diff changeset
1002 STAT_LABEL (total_used_map_size));
kono
parents: 68
diff changeset
1003 fprintf (stderr, "Ad-hoc table size: %5ld%c\n",
kono
parents: 68
diff changeset
1004 SCALE (s.adhoc_table_size),
kono
parents: 68
diff changeset
1005 STAT_LABEL (s.adhoc_table_size));
kono
parents: 68
diff changeset
1006 fprintf (stderr, "Ad-hoc table entries used: %5ld\n",
kono
parents: 68
diff changeset
1007 s.adhoc_table_entries_used);
kono
parents: 68
diff changeset
1008 fprintf (stderr, "optimized_ranges: %i\n",
kono
parents: 68
diff changeset
1009 line_table->num_optimized_ranges);
kono
parents: 68
diff changeset
1010 fprintf (stderr, "unoptimized_ranges: %i\n",
kono
parents: 68
diff changeset
1011 line_table->num_unoptimized_ranges);
kono
parents: 68
diff changeset
1012
kono
parents: 68
diff changeset
1013 fprintf (stderr, "\n");
kono
parents: 68
diff changeset
1014 }
kono
parents: 68
diff changeset
1015
kono
parents: 68
diff changeset
1016 /* Get location one beyond the final location in ordinary map IDX. */
kono
parents: 68
diff changeset
1017
kono
parents: 68
diff changeset
1018 static source_location
kono
parents: 68
diff changeset
1019 get_end_location (struct line_maps *set, unsigned int idx)
kono
parents: 68
diff changeset
1020 {
kono
parents: 68
diff changeset
1021 if (idx == LINEMAPS_ORDINARY_USED (set) - 1)
kono
parents: 68
diff changeset
1022 return set->highest_location;
kono
parents: 68
diff changeset
1023
kono
parents: 68
diff changeset
1024 struct line_map *next_map = LINEMAPS_ORDINARY_MAP_AT (set, idx + 1);
kono
parents: 68
diff changeset
1025 return MAP_START_LOCATION (next_map);
kono
parents: 68
diff changeset
1026 }
kono
parents: 68
diff changeset
1027
kono
parents: 68
diff changeset
1028 /* Helper function for write_digit_row. */
kono
parents: 68
diff changeset
1029
kono
parents: 68
diff changeset
1030 static void
kono
parents: 68
diff changeset
1031 write_digit (FILE *stream, int digit)
kono
parents: 68
diff changeset
1032 {
kono
parents: 68
diff changeset
1033 fputc ('0' + (digit % 10), stream);
kono
parents: 68
diff changeset
1034 }
kono
parents: 68
diff changeset
1035
kono
parents: 68
diff changeset
1036 /* Helper function for dump_location_info.
kono
parents: 68
diff changeset
1037 Write a row of numbers to STREAM, numbering a source line,
kono
parents: 68
diff changeset
1038 giving the units, tens, hundreds etc of the column number. */
kono
parents: 68
diff changeset
1039
kono
parents: 68
diff changeset
1040 static void
kono
parents: 68
diff changeset
1041 write_digit_row (FILE *stream, int indent,
kono
parents: 68
diff changeset
1042 const line_map_ordinary *map,
kono
parents: 68
diff changeset
1043 source_location loc, int max_col, int divisor)
kono
parents: 68
diff changeset
1044 {
kono
parents: 68
diff changeset
1045 fprintf (stream, "%*c", indent, ' ');
kono
parents: 68
diff changeset
1046 fprintf (stream, "|");
kono
parents: 68
diff changeset
1047 for (int column = 1; column < max_col; column++)
kono
parents: 68
diff changeset
1048 {
kono
parents: 68
diff changeset
1049 source_location column_loc = loc + (column << map->m_range_bits);
kono
parents: 68
diff changeset
1050 write_digit (stream, column_loc / divisor);
kono
parents: 68
diff changeset
1051 }
kono
parents: 68
diff changeset
1052 fprintf (stream, "\n");
kono
parents: 68
diff changeset
1053 }
kono
parents: 68
diff changeset
1054
kono
parents: 68
diff changeset
1055 /* Write a half-closed (START) / half-open (END) interval of
kono
parents: 68
diff changeset
1056 source_location to STREAM. */
kono
parents: 68
diff changeset
1057
kono
parents: 68
diff changeset
1058 static void
kono
parents: 68
diff changeset
1059 dump_location_range (FILE *stream,
kono
parents: 68
diff changeset
1060 source_location start, source_location end)
kono
parents: 68
diff changeset
1061 {
kono
parents: 68
diff changeset
1062 fprintf (stream,
kono
parents: 68
diff changeset
1063 " source_location interval: %u <= loc < %u\n",
kono
parents: 68
diff changeset
1064 start, end);
kono
parents: 68
diff changeset
1065 }
kono
parents: 68
diff changeset
1066
kono
parents: 68
diff changeset
1067 /* Write a labelled description of a half-closed (START) / half-open (END)
kono
parents: 68
diff changeset
1068 interval of source_location to STREAM. */
kono
parents: 68
diff changeset
1069
kono
parents: 68
diff changeset
1070 static void
kono
parents: 68
diff changeset
1071 dump_labelled_location_range (FILE *stream,
kono
parents: 68
diff changeset
1072 const char *name,
kono
parents: 68
diff changeset
1073 source_location start, source_location end)
kono
parents: 68
diff changeset
1074 {
kono
parents: 68
diff changeset
1075 fprintf (stream, "%s\n", name);
kono
parents: 68
diff changeset
1076 dump_location_range (stream, start, end);
kono
parents: 68
diff changeset
1077 fprintf (stream, "\n");
kono
parents: 68
diff changeset
1078 }
kono
parents: 68
diff changeset
1079
kono
parents: 68
diff changeset
1080 /* Write a visualization of the locations in the line_table to STREAM. */
kono
parents: 68
diff changeset
1081
kono
parents: 68
diff changeset
1082 void
kono
parents: 68
diff changeset
1083 dump_location_info (FILE *stream)
kono
parents: 68
diff changeset
1084 {
kono
parents: 68
diff changeset
1085 /* Visualize the reserved locations. */
kono
parents: 68
diff changeset
1086 dump_labelled_location_range (stream, "RESERVED LOCATIONS",
kono
parents: 68
diff changeset
1087 0, RESERVED_LOCATION_COUNT);
kono
parents: 68
diff changeset
1088
kono
parents: 68
diff changeset
1089 /* Visualize the ordinary line_map instances, rendering the sources. */
kono
parents: 68
diff changeset
1090 for (unsigned int idx = 0; idx < LINEMAPS_ORDINARY_USED (line_table); idx++)
kono
parents: 68
diff changeset
1091 {
kono
parents: 68
diff changeset
1092 source_location end_location = get_end_location (line_table, idx);
kono
parents: 68
diff changeset
1093 /* half-closed: doesn't include this one. */
kono
parents: 68
diff changeset
1094
kono
parents: 68
diff changeset
1095 const line_map_ordinary *map
kono
parents: 68
diff changeset
1096 = LINEMAPS_ORDINARY_MAP_AT (line_table, idx);
kono
parents: 68
diff changeset
1097 fprintf (stream, "ORDINARY MAP: %i\n", idx);
kono
parents: 68
diff changeset
1098 dump_location_range (stream,
kono
parents: 68
diff changeset
1099 MAP_START_LOCATION (map), end_location);
kono
parents: 68
diff changeset
1100 fprintf (stream, " file: %s\n", ORDINARY_MAP_FILE_NAME (map));
kono
parents: 68
diff changeset
1101 fprintf (stream, " starting at line: %i\n",
kono
parents: 68
diff changeset
1102 ORDINARY_MAP_STARTING_LINE_NUMBER (map));
kono
parents: 68
diff changeset
1103 fprintf (stream, " column and range bits: %i\n",
kono
parents: 68
diff changeset
1104 map->m_column_and_range_bits);
kono
parents: 68
diff changeset
1105 fprintf (stream, " column bits: %i\n",
kono
parents: 68
diff changeset
1106 map->m_column_and_range_bits - map->m_range_bits);
kono
parents: 68
diff changeset
1107 fprintf (stream, " range bits: %i\n",
kono
parents: 68
diff changeset
1108 map->m_range_bits);
kono
parents: 68
diff changeset
1109
kono
parents: 68
diff changeset
1110 /* Render the span of source lines that this "map" covers. */
kono
parents: 68
diff changeset
1111 for (source_location loc = MAP_START_LOCATION (map);
kono
parents: 68
diff changeset
1112 loc < end_location;
kono
parents: 68
diff changeset
1113 loc += (1 << map->m_range_bits) )
kono
parents: 68
diff changeset
1114 {
kono
parents: 68
diff changeset
1115 gcc_assert (pure_location_p (line_table, loc) );
kono
parents: 68
diff changeset
1116
kono
parents: 68
diff changeset
1117 expanded_location exploc
kono
parents: 68
diff changeset
1118 = linemap_expand_location (line_table, map, loc);
kono
parents: 68
diff changeset
1119
kono
parents: 68
diff changeset
1120 if (0 == exploc.column)
kono
parents: 68
diff changeset
1121 {
kono
parents: 68
diff changeset
1122 /* Beginning of a new source line: draw the line. */
kono
parents: 68
diff changeset
1123
kono
parents: 68
diff changeset
1124 int line_size;
kono
parents: 68
diff changeset
1125 const char *line_text = location_get_source_line (exploc.file,
kono
parents: 68
diff changeset
1126 exploc.line,
kono
parents: 68
diff changeset
1127 &line_size);
kono
parents: 68
diff changeset
1128 if (!line_text)
kono
parents: 68
diff changeset
1129 break;
kono
parents: 68
diff changeset
1130 fprintf (stream,
kono
parents: 68
diff changeset
1131 "%s:%3i|loc:%5i|%.*s\n",
kono
parents: 68
diff changeset
1132 exploc.file, exploc.line,
kono
parents: 68
diff changeset
1133 loc,
kono
parents: 68
diff changeset
1134 line_size, line_text);
kono
parents: 68
diff changeset
1135
kono
parents: 68
diff changeset
1136 /* "loc" is at column 0, which means "the whole line".
kono
parents: 68
diff changeset
1137 Render the locations *within* the line, by underlining
kono
parents: 68
diff changeset
1138 it, showing the source_location numeric values
kono
parents: 68
diff changeset
1139 at each column. */
kono
parents: 68
diff changeset
1140 int max_col = (1 << map->m_column_and_range_bits) - 1;
kono
parents: 68
diff changeset
1141 if (max_col > line_size)
kono
parents: 68
diff changeset
1142 max_col = line_size + 1;
kono
parents: 68
diff changeset
1143
kono
parents: 68
diff changeset
1144 int indent = 14 + strlen (exploc.file);
kono
parents: 68
diff changeset
1145
kono
parents: 68
diff changeset
1146 /* Thousands. */
kono
parents: 68
diff changeset
1147 if (end_location > 999)
kono
parents: 68
diff changeset
1148 write_digit_row (stream, indent, map, loc, max_col, 1000);
kono
parents: 68
diff changeset
1149
kono
parents: 68
diff changeset
1150 /* Hundreds. */
kono
parents: 68
diff changeset
1151 if (end_location > 99)
kono
parents: 68
diff changeset
1152 write_digit_row (stream, indent, map, loc, max_col, 100);
kono
parents: 68
diff changeset
1153
kono
parents: 68
diff changeset
1154 /* Tens. */
kono
parents: 68
diff changeset
1155 write_digit_row (stream, indent, map, loc, max_col, 10);
kono
parents: 68
diff changeset
1156
kono
parents: 68
diff changeset
1157 /* Units. */
kono
parents: 68
diff changeset
1158 write_digit_row (stream, indent, map, loc, max_col, 1);
kono
parents: 68
diff changeset
1159 }
kono
parents: 68
diff changeset
1160 }
kono
parents: 68
diff changeset
1161 fprintf (stream, "\n");
kono
parents: 68
diff changeset
1162 }
kono
parents: 68
diff changeset
1163
kono
parents: 68
diff changeset
1164 /* Visualize unallocated values. */
kono
parents: 68
diff changeset
1165 dump_labelled_location_range (stream, "UNALLOCATED LOCATIONS",
kono
parents: 68
diff changeset
1166 line_table->highest_location,
kono
parents: 68
diff changeset
1167 LINEMAPS_MACRO_LOWEST_LOCATION (line_table));
kono
parents: 68
diff changeset
1168
kono
parents: 68
diff changeset
1169 /* Visualize the macro line_map instances, rendering the sources. */
kono
parents: 68
diff changeset
1170 for (unsigned int i = 0; i < LINEMAPS_MACRO_USED (line_table); i++)
kono
parents: 68
diff changeset
1171 {
kono
parents: 68
diff changeset
1172 /* Each macro map that is allocated owns source_location values
kono
parents: 68
diff changeset
1173 that are *lower* that the one before them.
kono
parents: 68
diff changeset
1174 Hence it's meaningful to view them either in order of ascending
kono
parents: 68
diff changeset
1175 source locations, or in order of ascending macro map index. */
kono
parents: 68
diff changeset
1176 const bool ascending_source_locations = true;
kono
parents: 68
diff changeset
1177 unsigned int idx = (ascending_source_locations
kono
parents: 68
diff changeset
1178 ? (LINEMAPS_MACRO_USED (line_table) - (i + 1))
kono
parents: 68
diff changeset
1179 : i);
kono
parents: 68
diff changeset
1180 const line_map_macro *map = LINEMAPS_MACRO_MAP_AT (line_table, idx);
kono
parents: 68
diff changeset
1181 fprintf (stream, "MACRO %i: %s (%u tokens)\n",
kono
parents: 68
diff changeset
1182 idx,
kono
parents: 68
diff changeset
1183 linemap_map_get_macro_name (map),
kono
parents: 68
diff changeset
1184 MACRO_MAP_NUM_MACRO_TOKENS (map));
kono
parents: 68
diff changeset
1185 dump_location_range (stream,
kono
parents: 68
diff changeset
1186 map->start_location,
kono
parents: 68
diff changeset
1187 (map->start_location
kono
parents: 68
diff changeset
1188 + MACRO_MAP_NUM_MACRO_TOKENS (map)));
kono
parents: 68
diff changeset
1189 inform (MACRO_MAP_EXPANSION_POINT_LOCATION (map),
kono
parents: 68
diff changeset
1190 "expansion point is location %i",
kono
parents: 68
diff changeset
1191 MACRO_MAP_EXPANSION_POINT_LOCATION (map));
kono
parents: 68
diff changeset
1192 fprintf (stream, " map->start_location: %u\n",
kono
parents: 68
diff changeset
1193 map->start_location);
kono
parents: 68
diff changeset
1194
kono
parents: 68
diff changeset
1195 fprintf (stream, " macro_locations:\n");
kono
parents: 68
diff changeset
1196 for (unsigned int i = 0; i < MACRO_MAP_NUM_MACRO_TOKENS (map); i++)
kono
parents: 68
diff changeset
1197 {
kono
parents: 68
diff changeset
1198 source_location x = MACRO_MAP_LOCATIONS (map)[2 * i];
kono
parents: 68
diff changeset
1199 source_location y = MACRO_MAP_LOCATIONS (map)[(2 * i) + 1];
kono
parents: 68
diff changeset
1200
kono
parents: 68
diff changeset
1201 /* linemap_add_macro_token encodes token numbers in an expansion
kono
parents: 68
diff changeset
1202 by putting them after MAP_START_LOCATION. */
kono
parents: 68
diff changeset
1203
kono
parents: 68
diff changeset
1204 /* I'm typically seeing 4 uninitialized entries at the end of
kono
parents: 68
diff changeset
1205 0xafafafaf.
kono
parents: 68
diff changeset
1206 This appears to be due to macro.c:replace_args
kono
parents: 68
diff changeset
1207 adding 2 extra args for padding tokens; presumably there may
kono
parents: 68
diff changeset
1208 be a leading and/or trailing padding token injected,
kono
parents: 68
diff changeset
1209 each for 2 more location slots.
kono
parents: 68
diff changeset
1210 This would explain there being up to 4 source_locations slots
kono
parents: 68
diff changeset
1211 that may be uninitialized. */
kono
parents: 68
diff changeset
1212
kono
parents: 68
diff changeset
1213 fprintf (stream, " %u: %u, %u\n",
kono
parents: 68
diff changeset
1214 i,
kono
parents: 68
diff changeset
1215 x,
kono
parents: 68
diff changeset
1216 y);
kono
parents: 68
diff changeset
1217 if (x == y)
kono
parents: 68
diff changeset
1218 {
kono
parents: 68
diff changeset
1219 if (x < MAP_START_LOCATION (map))
kono
parents: 68
diff changeset
1220 inform (x, "token %u has x-location == y-location == %u", i, x);
kono
parents: 68
diff changeset
1221 else
kono
parents: 68
diff changeset
1222 fprintf (stream,
kono
parents: 68
diff changeset
1223 "x-location == y-location == %u encodes token # %u\n",
kono
parents: 68
diff changeset
1224 x, x - MAP_START_LOCATION (map));
kono
parents: 68
diff changeset
1225 }
kono
parents: 68
diff changeset
1226 else
kono
parents: 68
diff changeset
1227 {
kono
parents: 68
diff changeset
1228 inform (x, "token %u has x-location == %u", i, x);
kono
parents: 68
diff changeset
1229 inform (x, "token %u has y-location == %u", i, y);
kono
parents: 68
diff changeset
1230 }
kono
parents: 68
diff changeset
1231 }
kono
parents: 68
diff changeset
1232 fprintf (stream, "\n");
kono
parents: 68
diff changeset
1233 }
kono
parents: 68
diff changeset
1234
kono
parents: 68
diff changeset
1235 /* It appears that MAX_SOURCE_LOCATION itself is never assigned to a
kono
parents: 68
diff changeset
1236 macro map, presumably due to an off-by-one error somewhere
kono
parents: 68
diff changeset
1237 between the logic in linemap_enter_macro and
kono
parents: 68
diff changeset
1238 LINEMAPS_MACRO_LOWEST_LOCATION. */
kono
parents: 68
diff changeset
1239 dump_labelled_location_range (stream, "MAX_SOURCE_LOCATION",
kono
parents: 68
diff changeset
1240 MAX_SOURCE_LOCATION,
kono
parents: 68
diff changeset
1241 MAX_SOURCE_LOCATION + 1);
kono
parents: 68
diff changeset
1242
kono
parents: 68
diff changeset
1243 /* Visualize ad-hoc values. */
kono
parents: 68
diff changeset
1244 dump_labelled_location_range (stream, "AD-HOC LOCATIONS",
kono
parents: 68
diff changeset
1245 MAX_SOURCE_LOCATION + 1, UINT_MAX);
kono
parents: 68
diff changeset
1246 }
kono
parents: 68
diff changeset
1247
kono
parents: 68
diff changeset
1248 /* string_concat's constructor. */
kono
parents: 68
diff changeset
1249
kono
parents: 68
diff changeset
1250 string_concat::string_concat (int num, location_t *locs)
kono
parents: 68
diff changeset
1251 : m_num (num)
kono
parents: 68
diff changeset
1252 {
kono
parents: 68
diff changeset
1253 m_locs = ggc_vec_alloc <location_t> (num);
kono
parents: 68
diff changeset
1254 for (int i = 0; i < num; i++)
kono
parents: 68
diff changeset
1255 m_locs[i] = locs[i];
kono
parents: 68
diff changeset
1256 }
kono
parents: 68
diff changeset
1257
kono
parents: 68
diff changeset
1258 /* string_concat_db's constructor. */
kono
parents: 68
diff changeset
1259
kono
parents: 68
diff changeset
1260 string_concat_db::string_concat_db ()
kono
parents: 68
diff changeset
1261 {
kono
parents: 68
diff changeset
1262 m_table = hash_map <location_hash, string_concat *>::create_ggc (64);
kono
parents: 68
diff changeset
1263 }
kono
parents: 68
diff changeset
1264
kono
parents: 68
diff changeset
1265 /* Record that a string concatenation occurred, covering NUM
kono
parents: 68
diff changeset
1266 string literal tokens. LOCS is an array of size NUM, containing the
kono
parents: 68
diff changeset
1267 locations of the tokens. A copy of LOCS is taken. */
kono
parents: 68
diff changeset
1268
kono
parents: 68
diff changeset
1269 void
kono
parents: 68
diff changeset
1270 string_concat_db::record_string_concatenation (int num, location_t *locs)
kono
parents: 68
diff changeset
1271 {
kono
parents: 68
diff changeset
1272 gcc_assert (num > 1);
kono
parents: 68
diff changeset
1273 gcc_assert (locs);
kono
parents: 68
diff changeset
1274
kono
parents: 68
diff changeset
1275 location_t key_loc = get_key_loc (locs[0]);
kono
parents: 68
diff changeset
1276
kono
parents: 68
diff changeset
1277 string_concat *concat
kono
parents: 68
diff changeset
1278 = new (ggc_alloc <string_concat> ()) string_concat (num, locs);
kono
parents: 68
diff changeset
1279 m_table->put (key_loc, concat);
kono
parents: 68
diff changeset
1280 }
kono
parents: 68
diff changeset
1281
kono
parents: 68
diff changeset
1282 /* Determine if LOC was the location of the the initial token of a
kono
parents: 68
diff changeset
1283 concatenation of string literal tokens.
kono
parents: 68
diff changeset
1284 If so, *OUT_NUM is written to with the number of tokens, and
kono
parents: 68
diff changeset
1285 *OUT_LOCS with the location of an array of locations of the
kono
parents: 68
diff changeset
1286 tokens, and return true. *OUT_LOCS is a borrowed pointer to
kono
parents: 68
diff changeset
1287 storage owned by the string_concat_db.
kono
parents: 68
diff changeset
1288 Otherwise, return false. */
kono
parents: 68
diff changeset
1289
kono
parents: 68
diff changeset
1290 bool
kono
parents: 68
diff changeset
1291 string_concat_db::get_string_concatenation (location_t loc,
kono
parents: 68
diff changeset
1292 int *out_num,
kono
parents: 68
diff changeset
1293 location_t **out_locs)
kono
parents: 68
diff changeset
1294 {
kono
parents: 68
diff changeset
1295 gcc_assert (out_num);
kono
parents: 68
diff changeset
1296 gcc_assert (out_locs);
kono
parents: 68
diff changeset
1297
kono
parents: 68
diff changeset
1298 location_t key_loc = get_key_loc (loc);
kono
parents: 68
diff changeset
1299
kono
parents: 68
diff changeset
1300 string_concat **concat = m_table->get (key_loc);
kono
parents: 68
diff changeset
1301 if (!concat)
kono
parents: 68
diff changeset
1302 return false;
kono
parents: 68
diff changeset
1303
kono
parents: 68
diff changeset
1304 *out_num = (*concat)->m_num;
kono
parents: 68
diff changeset
1305 *out_locs =(*concat)->m_locs;
kono
parents: 68
diff changeset
1306 return true;
kono
parents: 68
diff changeset
1307 }
kono
parents: 68
diff changeset
1308
kono
parents: 68
diff changeset
1309 /* Internal function. Canonicalize LOC into a form suitable for
kono
parents: 68
diff changeset
1310 use as a key within the database, stripping away macro expansion,
kono
parents: 68
diff changeset
1311 ad-hoc information, and range information, using the location of
kono
parents: 68
diff changeset
1312 the start of LOC within an ordinary linemap. */
kono
parents: 68
diff changeset
1313
kono
parents: 68
diff changeset
1314 location_t
kono
parents: 68
diff changeset
1315 string_concat_db::get_key_loc (location_t loc)
kono
parents: 68
diff changeset
1316 {
kono
parents: 68
diff changeset
1317 loc = linemap_resolve_location (line_table, loc, LRK_SPELLING_LOCATION,
kono
parents: 68
diff changeset
1318 NULL);
kono
parents: 68
diff changeset
1319
kono
parents: 68
diff changeset
1320 loc = get_range_from_loc (line_table, loc).m_start;
kono
parents: 68
diff changeset
1321
kono
parents: 68
diff changeset
1322 return loc;
kono
parents: 68
diff changeset
1323 }
kono
parents: 68
diff changeset
1324
kono
parents: 68
diff changeset
1325 /* Helper class for use within get_substring_ranges_for_loc.
kono
parents: 68
diff changeset
1326 An vec of cpp_string with responsibility for releasing all of the
kono
parents: 68
diff changeset
1327 str->text for each str in the vector. */
kono
parents: 68
diff changeset
1328
kono
parents: 68
diff changeset
1329 class auto_cpp_string_vec : public auto_vec <cpp_string>
kono
parents: 68
diff changeset
1330 {
kono
parents: 68
diff changeset
1331 public:
kono
parents: 68
diff changeset
1332 auto_cpp_string_vec (int alloc)
kono
parents: 68
diff changeset
1333 : auto_vec <cpp_string> (alloc) {}
kono
parents: 68
diff changeset
1334
kono
parents: 68
diff changeset
1335 ~auto_cpp_string_vec ()
kono
parents: 68
diff changeset
1336 {
kono
parents: 68
diff changeset
1337 /* Clean up the copies within this vec. */
kono
parents: 68
diff changeset
1338 int i;
kono
parents: 68
diff changeset
1339 cpp_string *str;
kono
parents: 68
diff changeset
1340 FOR_EACH_VEC_ELT (*this, i, str)
kono
parents: 68
diff changeset
1341 free (const_cast <unsigned char *> (str->text));
kono
parents: 68
diff changeset
1342 }
kono
parents: 68
diff changeset
1343 };
kono
parents: 68
diff changeset
1344
kono
parents: 68
diff changeset
1345 /* Attempt to populate RANGES with source location information on the
kono
parents: 68
diff changeset
1346 individual characters within the string literal found at STRLOC.
kono
parents: 68
diff changeset
1347 If CONCATS is non-NULL, then any string literals that the token at
kono
parents: 68
diff changeset
1348 STRLOC was concatenated with are also added to RANGES.
kono
parents: 68
diff changeset
1349
kono
parents: 68
diff changeset
1350 Return NULL if successful, or an error message if any errors occurred (in
kono
parents: 68
diff changeset
1351 which case RANGES may be only partially populated and should not
kono
parents: 68
diff changeset
1352 be used).
kono
parents: 68
diff changeset
1353
kono
parents: 68
diff changeset
1354 This is implemented by re-parsing the relevant source line(s). */
kono
parents: 68
diff changeset
1355
kono
parents: 68
diff changeset
1356 static const char *
kono
parents: 68
diff changeset
1357 get_substring_ranges_for_loc (cpp_reader *pfile,
kono
parents: 68
diff changeset
1358 string_concat_db *concats,
kono
parents: 68
diff changeset
1359 location_t strloc,
kono
parents: 68
diff changeset
1360 enum cpp_ttype type,
kono
parents: 68
diff changeset
1361 cpp_substring_ranges &ranges)
kono
parents: 68
diff changeset
1362 {
kono
parents: 68
diff changeset
1363 gcc_assert (pfile);
kono
parents: 68
diff changeset
1364
kono
parents: 68
diff changeset
1365 if (strloc == UNKNOWN_LOCATION)
kono
parents: 68
diff changeset
1366 return "unknown location";
kono
parents: 68
diff changeset
1367
kono
parents: 68
diff changeset
1368 /* Reparsing the strings requires accurate location information.
kono
parents: 68
diff changeset
1369 If -ftrack-macro-expansion has been overridden from its default
kono
parents: 68
diff changeset
1370 of 2, then we might have a location of a macro expansion point,
kono
parents: 68
diff changeset
1371 rather than the location of the literal itself.
kono
parents: 68
diff changeset
1372 Avoid this by requiring that we have full macro expansion tracking
kono
parents: 68
diff changeset
1373 for substring locations to be available. */
kono
parents: 68
diff changeset
1374 if (cpp_get_options (pfile)->track_macro_expansion != 2)
kono
parents: 68
diff changeset
1375 return "track_macro_expansion != 2";
kono
parents: 68
diff changeset
1376
kono
parents: 68
diff changeset
1377 /* If #line or # 44 "file"-style directives are present, then there's
kono
parents: 68
diff changeset
1378 no guarantee that the line numbers we have can be used to locate
kono
parents: 68
diff changeset
1379 the strings. For example, we might have a .i file with # directives
kono
parents: 68
diff changeset
1380 pointing back to lines within a .c file, but the .c file might
kono
parents: 68
diff changeset
1381 have been edited since the .i file was created.
kono
parents: 68
diff changeset
1382 In such a case, the safest course is to disable on-demand substring
kono
parents: 68
diff changeset
1383 locations. */
kono
parents: 68
diff changeset
1384 if (line_table->seen_line_directive)
kono
parents: 68
diff changeset
1385 return "seen line directive";
kono
parents: 68
diff changeset
1386
kono
parents: 68
diff changeset
1387 /* If string concatenation has occurred at STRLOC, get the locations
kono
parents: 68
diff changeset
1388 of all of the literal tokens making up the compound string.
kono
parents: 68
diff changeset
1389 Otherwise, just use STRLOC. */
kono
parents: 68
diff changeset
1390 int num_locs = 1;
kono
parents: 68
diff changeset
1391 location_t *strlocs = &strloc;
kono
parents: 68
diff changeset
1392 if (concats)
kono
parents: 68
diff changeset
1393 concats->get_string_concatenation (strloc, &num_locs, &strlocs);
kono
parents: 68
diff changeset
1394
kono
parents: 68
diff changeset
1395 auto_cpp_string_vec strs (num_locs);
kono
parents: 68
diff changeset
1396 auto_vec <cpp_string_location_reader> loc_readers (num_locs);
kono
parents: 68
diff changeset
1397 for (int i = 0; i < num_locs; i++)
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1398 {
111
kono
parents: 68
diff changeset
1399 /* Get range of strloc. We will use it to locate the start and finish
kono
parents: 68
diff changeset
1400 of the literal token within the line. */
kono
parents: 68
diff changeset
1401 source_range src_range = get_range_from_loc (line_table, strlocs[i]);
kono
parents: 68
diff changeset
1402
kono
parents: 68
diff changeset
1403 if (src_range.m_start >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
kono
parents: 68
diff changeset
1404 /* If the string is within a macro expansion, we can't get at the
kono
parents: 68
diff changeset
1405 end location. */
kono
parents: 68
diff changeset
1406 return "macro expansion";
kono
parents: 68
diff changeset
1407
kono
parents: 68
diff changeset
1408 if (src_range.m_start >= LINE_MAP_MAX_LOCATION_WITH_COLS)
kono
parents: 68
diff changeset
1409 /* If so, we can't reliably determine where the token started within
kono
parents: 68
diff changeset
1410 its line. */
kono
parents: 68
diff changeset
1411 return "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS";
kono
parents: 68
diff changeset
1412
kono
parents: 68
diff changeset
1413 if (src_range.m_finish >= LINE_MAP_MAX_LOCATION_WITH_COLS)
kono
parents: 68
diff changeset
1414 /* If so, we can't reliably determine where the token finished within
kono
parents: 68
diff changeset
1415 its line. */
kono
parents: 68
diff changeset
1416 return "range ends after LINE_MAP_MAX_LOCATION_WITH_COLS";
kono
parents: 68
diff changeset
1417
kono
parents: 68
diff changeset
1418 expanded_location start
kono
parents: 68
diff changeset
1419 = expand_location_to_spelling_point (src_range.m_start);
kono
parents: 68
diff changeset
1420 expanded_location finish
kono
parents: 68
diff changeset
1421 = expand_location_to_spelling_point (src_range.m_finish);
kono
parents: 68
diff changeset
1422 if (start.file != finish.file)
kono
parents: 68
diff changeset
1423 return "range endpoints are in different files";
kono
parents: 68
diff changeset
1424 if (start.line != finish.line)
kono
parents: 68
diff changeset
1425 return "range endpoints are on different lines";
kono
parents: 68
diff changeset
1426 if (start.column > finish.column)
kono
parents: 68
diff changeset
1427 return "range endpoints are reversed";
kono
parents: 68
diff changeset
1428
kono
parents: 68
diff changeset
1429 int line_width;
kono
parents: 68
diff changeset
1430 const char *line = location_get_source_line (start.file, start.line,
kono
parents: 68
diff changeset
1431 &line_width);
kono
parents: 68
diff changeset
1432 if (line == NULL)
kono
parents: 68
diff changeset
1433 return "unable to read source line";
kono
parents: 68
diff changeset
1434
kono
parents: 68
diff changeset
1435 /* Determine the location of the literal (including quotes
kono
parents: 68
diff changeset
1436 and leading prefix chars, such as the 'u' in a u""
kono
parents: 68
diff changeset
1437 token). */
kono
parents: 68
diff changeset
1438 const char *literal = line + start.column - 1;
kono
parents: 68
diff changeset
1439 int literal_length = finish.column - start.column + 1;
kono
parents: 68
diff changeset
1440
kono
parents: 68
diff changeset
1441 /* Ensure that we don't crash if we got the wrong location. */
kono
parents: 68
diff changeset
1442 if (line_width < (start.column - 1 + literal_length))
kono
parents: 68
diff changeset
1443 return "line is not wide enough";
kono
parents: 68
diff changeset
1444
kono
parents: 68
diff changeset
1445 cpp_string from;
kono
parents: 68
diff changeset
1446 from.len = literal_length;
kono
parents: 68
diff changeset
1447 /* Make a copy of the literal, to avoid having to rely on
kono
parents: 68
diff changeset
1448 the lifetime of the copy of the line within the cache.
kono
parents: 68
diff changeset
1449 This will be released by the auto_cpp_string_vec dtor. */
kono
parents: 68
diff changeset
1450 from.text = XDUPVEC (unsigned char, literal, literal_length);
kono
parents: 68
diff changeset
1451 strs.safe_push (from);
kono
parents: 68
diff changeset
1452
kono
parents: 68
diff changeset
1453 /* For very long lines, a new linemap could have started
kono
parents: 68
diff changeset
1454 halfway through the token.
kono
parents: 68
diff changeset
1455 Ensure that the loc_reader uses the linemap of the
kono
parents: 68
diff changeset
1456 *end* of the token for its start location. */
kono
parents: 68
diff changeset
1457 const line_map_ordinary *final_ord_map;
kono
parents: 68
diff changeset
1458 linemap_resolve_location (line_table, src_range.m_finish,
kono
parents: 68
diff changeset
1459 LRK_MACRO_EXPANSION_POINT, &final_ord_map);
kono
parents: 68
diff changeset
1460 location_t start_loc
kono
parents: 68
diff changeset
1461 = linemap_position_for_line_and_column (line_table, final_ord_map,
kono
parents: 68
diff changeset
1462 start.line, start.column);
kono
parents: 68
diff changeset
1463
kono
parents: 68
diff changeset
1464 cpp_string_location_reader loc_reader (start_loc, line_table);
kono
parents: 68
diff changeset
1465 loc_readers.safe_push (loc_reader);
kono
parents: 68
diff changeset
1466 }
kono
parents: 68
diff changeset
1467
kono
parents: 68
diff changeset
1468 /* Rerun cpp_interpret_string, or rather, a modified version of it. */
kono
parents: 68
diff changeset
1469 const char *err = cpp_interpret_string_ranges (pfile, strs.address (),
kono
parents: 68
diff changeset
1470 loc_readers.address (),
kono
parents: 68
diff changeset
1471 num_locs, &ranges, type);
kono
parents: 68
diff changeset
1472 if (err)
kono
parents: 68
diff changeset
1473 return err;
kono
parents: 68
diff changeset
1474
kono
parents: 68
diff changeset
1475 /* Success: "ranges" should now contain information on the string. */
kono
parents: 68
diff changeset
1476 return NULL;
kono
parents: 68
diff changeset
1477 }
kono
parents: 68
diff changeset
1478
kono
parents: 68
diff changeset
1479 /* Attempt to populate *OUT_LOC with source location information on the
kono
parents: 68
diff changeset
1480 given characters within the string literal found at STRLOC.
kono
parents: 68
diff changeset
1481 CARET_IDX, START_IDX, and END_IDX refer to offsets within the execution
kono
parents: 68
diff changeset
1482 character set.
kono
parents: 68
diff changeset
1483
kono
parents: 68
diff changeset
1484 For example, given CARET_IDX = 4, START_IDX = 3, END_IDX = 7
kono
parents: 68
diff changeset
1485 and string literal "012345\n789"
kono
parents: 68
diff changeset
1486 *OUT_LOC is written to with:
kono
parents: 68
diff changeset
1487 "012345\n789"
kono
parents: 68
diff changeset
1488 ~^~~~~
kono
parents: 68
diff changeset
1489
kono
parents: 68
diff changeset
1490 If CONCATS is non-NULL, then any string literals that the token at
kono
parents: 68
diff changeset
1491 STRLOC was concatenated with are also considered.
kono
parents: 68
diff changeset
1492
kono
parents: 68
diff changeset
1493 This is implemented by re-parsing the relevant source line(s).
kono
parents: 68
diff changeset
1494
kono
parents: 68
diff changeset
1495 Return NULL if successful, or an error message if any errors occurred.
kono
parents: 68
diff changeset
1496 Error messages are intended for GCC developers (to help debugging) rather
kono
parents: 68
diff changeset
1497 than for end-users. */
kono
parents: 68
diff changeset
1498
kono
parents: 68
diff changeset
1499 const char *
kono
parents: 68
diff changeset
1500 get_source_location_for_substring (cpp_reader *pfile,
kono
parents: 68
diff changeset
1501 string_concat_db *concats,
kono
parents: 68
diff changeset
1502 location_t strloc,
kono
parents: 68
diff changeset
1503 enum cpp_ttype type,
kono
parents: 68
diff changeset
1504 int caret_idx, int start_idx, int end_idx,
kono
parents: 68
diff changeset
1505 source_location *out_loc)
kono
parents: 68
diff changeset
1506 {
kono
parents: 68
diff changeset
1507 gcc_checking_assert (caret_idx >= 0);
kono
parents: 68
diff changeset
1508 gcc_checking_assert (start_idx >= 0);
kono
parents: 68
diff changeset
1509 gcc_checking_assert (end_idx >= 0);
kono
parents: 68
diff changeset
1510 gcc_assert (out_loc);
kono
parents: 68
diff changeset
1511
kono
parents: 68
diff changeset
1512 cpp_substring_ranges ranges;
kono
parents: 68
diff changeset
1513 const char *err
kono
parents: 68
diff changeset
1514 = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
kono
parents: 68
diff changeset
1515 if (err)
kono
parents: 68
diff changeset
1516 return err;
kono
parents: 68
diff changeset
1517
kono
parents: 68
diff changeset
1518 if (caret_idx >= ranges.get_num_ranges ())
kono
parents: 68
diff changeset
1519 return "caret_idx out of range";
kono
parents: 68
diff changeset
1520 if (start_idx >= ranges.get_num_ranges ())
kono
parents: 68
diff changeset
1521 return "start_idx out of range";
kono
parents: 68
diff changeset
1522 if (end_idx >= ranges.get_num_ranges ())
kono
parents: 68
diff changeset
1523 return "end_idx out of range";
kono
parents: 68
diff changeset
1524
kono
parents: 68
diff changeset
1525 *out_loc = make_location (ranges.get_range (caret_idx).m_start,
kono
parents: 68
diff changeset
1526 ranges.get_range (start_idx).m_start,
kono
parents: 68
diff changeset
1527 ranges.get_range (end_idx).m_finish);
kono
parents: 68
diff changeset
1528 return NULL;
kono
parents: 68
diff changeset
1529 }
kono
parents: 68
diff changeset
1530
kono
parents: 68
diff changeset
1531 #if CHECKING_P
kono
parents: 68
diff changeset
1532
kono
parents: 68
diff changeset
1533 namespace selftest {
kono
parents: 68
diff changeset
1534
kono
parents: 68
diff changeset
1535 /* Selftests of location handling. */
kono
parents: 68
diff changeset
1536
kono
parents: 68
diff changeset
1537 /* Attempt to populate *OUT_RANGE with source location information on the
kono
parents: 68
diff changeset
1538 given character within the string literal found at STRLOC.
kono
parents: 68
diff changeset
1539 CHAR_IDX refers to an offset within the execution character set.
kono
parents: 68
diff changeset
1540 If CONCATS is non-NULL, then any string literals that the token at
kono
parents: 68
diff changeset
1541 STRLOC was concatenated with are also considered.
kono
parents: 68
diff changeset
1542
kono
parents: 68
diff changeset
1543 This is implemented by re-parsing the relevant source line(s).
kono
parents: 68
diff changeset
1544
kono
parents: 68
diff changeset
1545 Return NULL if successful, or an error message if any errors occurred.
kono
parents: 68
diff changeset
1546 Error messages are intended for GCC developers (to help debugging) rather
kono
parents: 68
diff changeset
1547 than for end-users. */
kono
parents: 68
diff changeset
1548
kono
parents: 68
diff changeset
1549 static const char *
kono
parents: 68
diff changeset
1550 get_source_range_for_char (cpp_reader *pfile,
kono
parents: 68
diff changeset
1551 string_concat_db *concats,
kono
parents: 68
diff changeset
1552 location_t strloc,
kono
parents: 68
diff changeset
1553 enum cpp_ttype type,
kono
parents: 68
diff changeset
1554 int char_idx,
kono
parents: 68
diff changeset
1555 source_range *out_range)
kono
parents: 68
diff changeset
1556 {
kono
parents: 68
diff changeset
1557 gcc_checking_assert (char_idx >= 0);
kono
parents: 68
diff changeset
1558 gcc_assert (out_range);
kono
parents: 68
diff changeset
1559
kono
parents: 68
diff changeset
1560 cpp_substring_ranges ranges;
kono
parents: 68
diff changeset
1561 const char *err
kono
parents: 68
diff changeset
1562 = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
kono
parents: 68
diff changeset
1563 if (err)
kono
parents: 68
diff changeset
1564 return err;
kono
parents: 68
diff changeset
1565
kono
parents: 68
diff changeset
1566 if (char_idx >= ranges.get_num_ranges ())
kono
parents: 68
diff changeset
1567 return "char_idx out of range";
kono
parents: 68
diff changeset
1568
kono
parents: 68
diff changeset
1569 *out_range = ranges.get_range (char_idx);
kono
parents: 68
diff changeset
1570 return NULL;
kono
parents: 68
diff changeset
1571 }
kono
parents: 68
diff changeset
1572
kono
parents: 68
diff changeset
1573 /* As get_source_range_for_char, but write to *OUT the number
kono
parents: 68
diff changeset
1574 of ranges that are available. */
kono
parents: 68
diff changeset
1575
kono
parents: 68
diff changeset
1576 static const char *
kono
parents: 68
diff changeset
1577 get_num_source_ranges_for_substring (cpp_reader *pfile,
kono
parents: 68
diff changeset
1578 string_concat_db *concats,
kono
parents: 68
diff changeset
1579 location_t strloc,
kono
parents: 68
diff changeset
1580 enum cpp_ttype type,
kono
parents: 68
diff changeset
1581 int *out)
kono
parents: 68
diff changeset
1582 {
kono
parents: 68
diff changeset
1583 gcc_assert (out);
kono
parents: 68
diff changeset
1584
kono
parents: 68
diff changeset
1585 cpp_substring_ranges ranges;
kono
parents: 68
diff changeset
1586 const char *err
kono
parents: 68
diff changeset
1587 = get_substring_ranges_for_loc (pfile, concats, strloc, type, ranges);
kono
parents: 68
diff changeset
1588
kono
parents: 68
diff changeset
1589 if (err)
kono
parents: 68
diff changeset
1590 return err;
kono
parents: 68
diff changeset
1591
kono
parents: 68
diff changeset
1592 *out = ranges.get_num_ranges ();
kono
parents: 68
diff changeset
1593 return NULL;
kono
parents: 68
diff changeset
1594 }
kono
parents: 68
diff changeset
1595
kono
parents: 68
diff changeset
1596 /* Selftests of location handling. */
kono
parents: 68
diff changeset
1597
kono
parents: 68
diff changeset
1598 /* Helper function for verifying location data: when location_t
kono
parents: 68
diff changeset
1599 values are > LINE_MAP_MAX_LOCATION_WITH_COLS, they are treated
kono
parents: 68
diff changeset
1600 as having column 0. */
kono
parents: 68
diff changeset
1601
kono
parents: 68
diff changeset
1602 static bool
kono
parents: 68
diff changeset
1603 should_have_column_data_p (location_t loc)
kono
parents: 68
diff changeset
1604 {
kono
parents: 68
diff changeset
1605 if (IS_ADHOC_LOC (loc))
kono
parents: 68
diff changeset
1606 loc = get_location_from_adhoc_loc (line_table, loc);
kono
parents: 68
diff changeset
1607 if (loc > LINE_MAP_MAX_LOCATION_WITH_COLS)
kono
parents: 68
diff changeset
1608 return false;
kono
parents: 68
diff changeset
1609 return true;
kono
parents: 68
diff changeset
1610 }
kono
parents: 68
diff changeset
1611
kono
parents: 68
diff changeset
1612 /* Selftest for should_have_column_data_p. */
kono
parents: 68
diff changeset
1613
kono
parents: 68
diff changeset
1614 static void
kono
parents: 68
diff changeset
1615 test_should_have_column_data_p ()
kono
parents: 68
diff changeset
1616 {
kono
parents: 68
diff changeset
1617 ASSERT_TRUE (should_have_column_data_p (RESERVED_LOCATION_COUNT));
kono
parents: 68
diff changeset
1618 ASSERT_TRUE
kono
parents: 68
diff changeset
1619 (should_have_column_data_p (LINE_MAP_MAX_LOCATION_WITH_COLS));
kono
parents: 68
diff changeset
1620 ASSERT_FALSE
kono
parents: 68
diff changeset
1621 (should_have_column_data_p (LINE_MAP_MAX_LOCATION_WITH_COLS + 1));
kono
parents: 68
diff changeset
1622 }
kono
parents: 68
diff changeset
1623
kono
parents: 68
diff changeset
1624 /* Verify the result of LOCATION_FILE/LOCATION_LINE/LOCATION_COLUMN
kono
parents: 68
diff changeset
1625 on LOC. */
kono
parents: 68
diff changeset
1626
kono
parents: 68
diff changeset
1627 static void
kono
parents: 68
diff changeset
1628 assert_loceq (const char *exp_filename, int exp_linenum, int exp_colnum,
kono
parents: 68
diff changeset
1629 location_t loc)
kono
parents: 68
diff changeset
1630 {
kono
parents: 68
diff changeset
1631 ASSERT_STREQ (exp_filename, LOCATION_FILE (loc));
kono
parents: 68
diff changeset
1632 ASSERT_EQ (exp_linenum, LOCATION_LINE (loc));
kono
parents: 68
diff changeset
1633 /* If location_t values are sufficiently high, then column numbers
kono
parents: 68
diff changeset
1634 will be unavailable and LOCATION_COLUMN (loc) will be 0.
kono
parents: 68
diff changeset
1635 When close to the threshold, column numbers *may* be present: if
kono
parents: 68
diff changeset
1636 the final linemap before the threshold contains a line that straddles
kono
parents: 68
diff changeset
1637 the threshold, locations in that line have column information. */
kono
parents: 68
diff changeset
1638 if (should_have_column_data_p (loc))
kono
parents: 68
diff changeset
1639 ASSERT_EQ (exp_colnum, LOCATION_COLUMN (loc));
kono
parents: 68
diff changeset
1640 }
kono
parents: 68
diff changeset
1641
kono
parents: 68
diff changeset
1642 /* Various selftests involve constructing a line table and one or more
kono
parents: 68
diff changeset
1643 line maps within it.
kono
parents: 68
diff changeset
1644
kono
parents: 68
diff changeset
1645 For maximum test coverage we want to run these tests with a variety
kono
parents: 68
diff changeset
1646 of situations:
kono
parents: 68
diff changeset
1647 - line_table->default_range_bits: some frontends use a non-zero value
kono
parents: 68
diff changeset
1648 and others use zero
kono
parents: 68
diff changeset
1649 - the fallback modes within line-map.c: there are various threshold
kono
parents: 68
diff changeset
1650 values for source_location/location_t beyond line-map.c changes
kono
parents: 68
diff changeset
1651 behavior (disabling of the range-packing optimization, disabling
kono
parents: 68
diff changeset
1652 of column-tracking). We can exercise these by starting the line_table
kono
parents: 68
diff changeset
1653 at interesting values at or near these thresholds.
kono
parents: 68
diff changeset
1654
kono
parents: 68
diff changeset
1655 The following struct describes a particular case within our test
kono
parents: 68
diff changeset
1656 matrix. */
kono
parents: 68
diff changeset
1657
kono
parents: 68
diff changeset
1658 struct line_table_case
kono
parents: 68
diff changeset
1659 {
kono
parents: 68
diff changeset
1660 line_table_case (int default_range_bits, int base_location)
kono
parents: 68
diff changeset
1661 : m_default_range_bits (default_range_bits),
kono
parents: 68
diff changeset
1662 m_base_location (base_location)
kono
parents: 68
diff changeset
1663 {}
kono
parents: 68
diff changeset
1664
kono
parents: 68
diff changeset
1665 int m_default_range_bits;
kono
parents: 68
diff changeset
1666 int m_base_location;
kono
parents: 68
diff changeset
1667 };
kono
parents: 68
diff changeset
1668
kono
parents: 68
diff changeset
1669 /* Constructor. Store the old value of line_table, and create a new
kono
parents: 68
diff changeset
1670 one, using sane defaults. */
kono
parents: 68
diff changeset
1671
kono
parents: 68
diff changeset
1672 line_table_test::line_table_test ()
kono
parents: 68
diff changeset
1673 {
kono
parents: 68
diff changeset
1674 gcc_assert (saved_line_table == NULL);
kono
parents: 68
diff changeset
1675 saved_line_table = line_table;
kono
parents: 68
diff changeset
1676 line_table = ggc_alloc<line_maps> ();
kono
parents: 68
diff changeset
1677 linemap_init (line_table, BUILTINS_LOCATION);
kono
parents: 68
diff changeset
1678 gcc_assert (saved_line_table->reallocator);
kono
parents: 68
diff changeset
1679 line_table->reallocator = saved_line_table->reallocator;
kono
parents: 68
diff changeset
1680 gcc_assert (saved_line_table->round_alloc_size);
kono
parents: 68
diff changeset
1681 line_table->round_alloc_size = saved_line_table->round_alloc_size;
kono
parents: 68
diff changeset
1682 line_table->default_range_bits = 0;
kono
parents: 68
diff changeset
1683 }
kono
parents: 68
diff changeset
1684
kono
parents: 68
diff changeset
1685 /* Constructor. Store the old value of line_table, and create a new
kono
parents: 68
diff changeset
1686 one, using the sitation described in CASE_. */
kono
parents: 68
diff changeset
1687
kono
parents: 68
diff changeset
1688 line_table_test::line_table_test (const line_table_case &case_)
kono
parents: 68
diff changeset
1689 {
kono
parents: 68
diff changeset
1690 gcc_assert (saved_line_table == NULL);
kono
parents: 68
diff changeset
1691 saved_line_table = line_table;
kono
parents: 68
diff changeset
1692 line_table = ggc_alloc<line_maps> ();
kono
parents: 68
diff changeset
1693 linemap_init (line_table, BUILTINS_LOCATION);
kono
parents: 68
diff changeset
1694 gcc_assert (saved_line_table->reallocator);
kono
parents: 68
diff changeset
1695 line_table->reallocator = saved_line_table->reallocator;
kono
parents: 68
diff changeset
1696 gcc_assert (saved_line_table->round_alloc_size);
kono
parents: 68
diff changeset
1697 line_table->round_alloc_size = saved_line_table->round_alloc_size;
kono
parents: 68
diff changeset
1698 line_table->default_range_bits = case_.m_default_range_bits;
kono
parents: 68
diff changeset
1699 if (case_.m_base_location)
kono
parents: 68
diff changeset
1700 {
kono
parents: 68
diff changeset
1701 line_table->highest_location = case_.m_base_location;
kono
parents: 68
diff changeset
1702 line_table->highest_line = case_.m_base_location;
kono
parents: 68
diff changeset
1703 }
kono
parents: 68
diff changeset
1704 }
kono
parents: 68
diff changeset
1705
kono
parents: 68
diff changeset
1706 /* Destructor. Restore the old value of line_table. */
kono
parents: 68
diff changeset
1707
kono
parents: 68
diff changeset
1708 line_table_test::~line_table_test ()
kono
parents: 68
diff changeset
1709 {
kono
parents: 68
diff changeset
1710 gcc_assert (saved_line_table != NULL);
kono
parents: 68
diff changeset
1711 line_table = saved_line_table;
kono
parents: 68
diff changeset
1712 saved_line_table = NULL;
kono
parents: 68
diff changeset
1713 }
kono
parents: 68
diff changeset
1714
kono
parents: 68
diff changeset
1715 /* Verify basic operation of ordinary linemaps. */
kono
parents: 68
diff changeset
1716
kono
parents: 68
diff changeset
1717 static void
kono
parents: 68
diff changeset
1718 test_accessing_ordinary_linemaps (const line_table_case &case_)
kono
parents: 68
diff changeset
1719 {
kono
parents: 68
diff changeset
1720 line_table_test ltt (case_);
kono
parents: 68
diff changeset
1721
kono
parents: 68
diff changeset
1722 /* Build a simple linemap describing some locations. */
kono
parents: 68
diff changeset
1723 linemap_add (line_table, LC_ENTER, false, "foo.c", 0);
kono
parents: 68
diff changeset
1724
kono
parents: 68
diff changeset
1725 linemap_line_start (line_table, 1, 100);
kono
parents: 68
diff changeset
1726 location_t loc_a = linemap_position_for_column (line_table, 1);
kono
parents: 68
diff changeset
1727 location_t loc_b = linemap_position_for_column (line_table, 23);
kono
parents: 68
diff changeset
1728
kono
parents: 68
diff changeset
1729 linemap_line_start (line_table, 2, 100);
kono
parents: 68
diff changeset
1730 location_t loc_c = linemap_position_for_column (line_table, 1);
kono
parents: 68
diff changeset
1731 location_t loc_d = linemap_position_for_column (line_table, 17);
kono
parents: 68
diff changeset
1732
kono
parents: 68
diff changeset
1733 /* Example of a very long line. */
kono
parents: 68
diff changeset
1734 linemap_line_start (line_table, 3, 2000);
kono
parents: 68
diff changeset
1735 location_t loc_e = linemap_position_for_column (line_table, 700);
kono
parents: 68
diff changeset
1736
kono
parents: 68
diff changeset
1737 /* Transitioning back to a short line. */
kono
parents: 68
diff changeset
1738 linemap_line_start (line_table, 4, 0);
kono
parents: 68
diff changeset
1739 location_t loc_back_to_short = linemap_position_for_column (line_table, 100);
kono
parents: 68
diff changeset
1740
kono
parents: 68
diff changeset
1741 if (should_have_column_data_p (loc_back_to_short))
kono
parents: 68
diff changeset
1742 {
kono
parents: 68
diff changeset
1743 /* Verify that we switched to short lines in the linemap. */
kono
parents: 68
diff changeset
1744 line_map_ordinary *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
kono
parents: 68
diff changeset
1745 ASSERT_EQ (7, map->m_column_and_range_bits - map->m_range_bits);
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1746 }
111
kono
parents: 68
diff changeset
1747
kono
parents: 68
diff changeset
1748 /* Example of a line that will eventually be seen to be longer
kono
parents: 68
diff changeset
1749 than LINE_MAP_MAX_COLUMN_NUMBER; the initially seen width is
kono
parents: 68
diff changeset
1750 below that. */
kono
parents: 68
diff changeset
1751 linemap_line_start (line_table, 5, 2000);
kono
parents: 68
diff changeset
1752
kono
parents: 68
diff changeset
1753 location_t loc_start_of_very_long_line
kono
parents: 68
diff changeset
1754 = linemap_position_for_column (line_table, 2000);
kono
parents: 68
diff changeset
1755 location_t loc_too_wide
kono
parents: 68
diff changeset
1756 = linemap_position_for_column (line_table, 4097);
kono
parents: 68
diff changeset
1757 location_t loc_too_wide_2
kono
parents: 68
diff changeset
1758 = linemap_position_for_column (line_table, 4098);
kono
parents: 68
diff changeset
1759
kono
parents: 68
diff changeset
1760 /* ...and back to a sane line length. */
kono
parents: 68
diff changeset
1761 linemap_line_start (line_table, 6, 100);
kono
parents: 68
diff changeset
1762 location_t loc_sane_again = linemap_position_for_column (line_table, 10);
kono
parents: 68
diff changeset
1763
kono
parents: 68
diff changeset
1764 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
kono
parents: 68
diff changeset
1765
kono
parents: 68
diff changeset
1766 /* Multiple files. */
kono
parents: 68
diff changeset
1767 linemap_add (line_table, LC_ENTER, false, "bar.c", 0);
kono
parents: 68
diff changeset
1768 linemap_line_start (line_table, 1, 200);
kono
parents: 68
diff changeset
1769 location_t loc_f = linemap_position_for_column (line_table, 150);
kono
parents: 68
diff changeset
1770 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
kono
parents: 68
diff changeset
1771
kono
parents: 68
diff changeset
1772 /* Verify that we can recover the location info. */
kono
parents: 68
diff changeset
1773 assert_loceq ("foo.c", 1, 1, loc_a);
kono
parents: 68
diff changeset
1774 assert_loceq ("foo.c", 1, 23, loc_b);
kono
parents: 68
diff changeset
1775 assert_loceq ("foo.c", 2, 1, loc_c);
kono
parents: 68
diff changeset
1776 assert_loceq ("foo.c", 2, 17, loc_d);
kono
parents: 68
diff changeset
1777 assert_loceq ("foo.c", 3, 700, loc_e);
kono
parents: 68
diff changeset
1778 assert_loceq ("foo.c", 4, 100, loc_back_to_short);
kono
parents: 68
diff changeset
1779
kono
parents: 68
diff changeset
1780 /* In the very wide line, the initial location should be fully tracked. */
kono
parents: 68
diff changeset
1781 assert_loceq ("foo.c", 5, 2000, loc_start_of_very_long_line);
kono
parents: 68
diff changeset
1782 /* ...but once we exceed LINE_MAP_MAX_COLUMN_NUMBER column-tracking should
kono
parents: 68
diff changeset
1783 be disabled. */
kono
parents: 68
diff changeset
1784 assert_loceq ("foo.c", 5, 0, loc_too_wide);
kono
parents: 68
diff changeset
1785 assert_loceq ("foo.c", 5, 0, loc_too_wide_2);
kono
parents: 68
diff changeset
1786 /*...and column-tracking should be re-enabled for subsequent lines. */
kono
parents: 68
diff changeset
1787 assert_loceq ("foo.c", 6, 10, loc_sane_again);
kono
parents: 68
diff changeset
1788
kono
parents: 68
diff changeset
1789 assert_loceq ("bar.c", 1, 150, loc_f);
kono
parents: 68
diff changeset
1790
kono
parents: 68
diff changeset
1791 ASSERT_FALSE (is_location_from_builtin_token (loc_a));
kono
parents: 68
diff changeset
1792 ASSERT_TRUE (pure_location_p (line_table, loc_a));
kono
parents: 68
diff changeset
1793
kono
parents: 68
diff changeset
1794 /* Verify using make_location to build a range, and extracting data
kono
parents: 68
diff changeset
1795 back from it. */
kono
parents: 68
diff changeset
1796 location_t range_c_b_d = make_location (loc_c, loc_b, loc_d);
kono
parents: 68
diff changeset
1797 ASSERT_FALSE (pure_location_p (line_table, range_c_b_d));
kono
parents: 68
diff changeset
1798 ASSERT_EQ (loc_c, get_location_from_adhoc_loc (line_table, range_c_b_d));
kono
parents: 68
diff changeset
1799 source_range src_range = get_range_from_loc (line_table, range_c_b_d);
kono
parents: 68
diff changeset
1800 ASSERT_EQ (loc_b, src_range.m_start);
kono
parents: 68
diff changeset
1801 ASSERT_EQ (loc_d, src_range.m_finish);
kono
parents: 68
diff changeset
1802 }
kono
parents: 68
diff changeset
1803
kono
parents: 68
diff changeset
1804 /* Verify various properties of UNKNOWN_LOCATION. */
kono
parents: 68
diff changeset
1805
kono
parents: 68
diff changeset
1806 static void
kono
parents: 68
diff changeset
1807 test_unknown_location ()
kono
parents: 68
diff changeset
1808 {
kono
parents: 68
diff changeset
1809 ASSERT_EQ (NULL, LOCATION_FILE (UNKNOWN_LOCATION));
kono
parents: 68
diff changeset
1810 ASSERT_EQ (0, LOCATION_LINE (UNKNOWN_LOCATION));
kono
parents: 68
diff changeset
1811 ASSERT_EQ (0, LOCATION_COLUMN (UNKNOWN_LOCATION));
kono
parents: 68
diff changeset
1812 }
kono
parents: 68
diff changeset
1813
kono
parents: 68
diff changeset
1814 /* Verify various properties of BUILTINS_LOCATION. */
kono
parents: 68
diff changeset
1815
kono
parents: 68
diff changeset
1816 static void
kono
parents: 68
diff changeset
1817 test_builtins ()
kono
parents: 68
diff changeset
1818 {
kono
parents: 68
diff changeset
1819 assert_loceq (_("<built-in>"), 0, 0, BUILTINS_LOCATION);
kono
parents: 68
diff changeset
1820 ASSERT_PRED1 (is_location_from_builtin_token, BUILTINS_LOCATION);
kono
parents: 68
diff changeset
1821 }
kono
parents: 68
diff changeset
1822
kono
parents: 68
diff changeset
1823 /* Regression test for make_location.
kono
parents: 68
diff changeset
1824 Ensure that we use pure locations for the start/finish of the range,
kono
parents: 68
diff changeset
1825 rather than storing a packed or ad-hoc range as the start/finish. */
kono
parents: 68
diff changeset
1826
kono
parents: 68
diff changeset
1827 static void
kono
parents: 68
diff changeset
1828 test_make_location_nonpure_range_endpoints (const line_table_case &case_)
kono
parents: 68
diff changeset
1829 {
kono
parents: 68
diff changeset
1830 /* Issue seen with testsuite/c-c++-common/Wlogical-not-parentheses-2.c
kono
parents: 68
diff changeset
1831 with C++ frontend.
kono
parents: 68
diff changeset
1832 ....................0000000001111111111222.
kono
parents: 68
diff changeset
1833 ....................1234567890123456789012. */
kono
parents: 68
diff changeset
1834 const char *content = " r += !aaa == bbb;\n";
kono
parents: 68
diff changeset
1835 temp_source_file tmp (SELFTEST_LOCATION, ".C", content);
kono
parents: 68
diff changeset
1836 line_table_test ltt (case_);
kono
parents: 68
diff changeset
1837 linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
kono
parents: 68
diff changeset
1838
kono
parents: 68
diff changeset
1839 const location_t c11 = linemap_position_for_column (line_table, 11);
kono
parents: 68
diff changeset
1840 const location_t c12 = linemap_position_for_column (line_table, 12);
kono
parents: 68
diff changeset
1841 const location_t c13 = linemap_position_for_column (line_table, 13);
kono
parents: 68
diff changeset
1842 const location_t c14 = linemap_position_for_column (line_table, 14);
kono
parents: 68
diff changeset
1843 const location_t c21 = linemap_position_for_column (line_table, 21);
kono
parents: 68
diff changeset
1844
kono
parents: 68
diff changeset
1845 if (c21 > LINE_MAP_MAX_LOCATION_WITH_COLS)
kono
parents: 68
diff changeset
1846 return;
kono
parents: 68
diff changeset
1847
kono
parents: 68
diff changeset
1848 /* Use column 13 for the caret location, arbitrarily, to verify that we
kono
parents: 68
diff changeset
1849 handle start != caret. */
kono
parents: 68
diff changeset
1850 const location_t aaa = make_location (c13, c12, c14);
kono
parents: 68
diff changeset
1851 ASSERT_EQ (c13, get_pure_location (aaa));
kono
parents: 68
diff changeset
1852 ASSERT_EQ (c12, get_start (aaa));
kono
parents: 68
diff changeset
1853 ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa)));
kono
parents: 68
diff changeset
1854 ASSERT_EQ (c14, get_finish (aaa));
kono
parents: 68
diff changeset
1855 ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa)));
kono
parents: 68
diff changeset
1856
kono
parents: 68
diff changeset
1857 /* Make a location using a location with a range as the start-point. */
kono
parents: 68
diff changeset
1858 const location_t not_aaa = make_location (c11, aaa, c14);
kono
parents: 68
diff changeset
1859 ASSERT_EQ (c11, get_pure_location (not_aaa));
kono
parents: 68
diff changeset
1860 /* It should use the start location of the range, not store the range
kono
parents: 68
diff changeset
1861 itself. */
kono
parents: 68
diff changeset
1862 ASSERT_EQ (c12, get_start (not_aaa));
kono
parents: 68
diff changeset
1863 ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa)));
kono
parents: 68
diff changeset
1864 ASSERT_EQ (c14, get_finish (not_aaa));
kono
parents: 68
diff changeset
1865 ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa)));
kono
parents: 68
diff changeset
1866
kono
parents: 68
diff changeset
1867 /* Similarly, make a location with a range as the end-point. */
kono
parents: 68
diff changeset
1868 const location_t aaa_eq_bbb = make_location (c12, c12, c21);
kono
parents: 68
diff changeset
1869 ASSERT_EQ (c12, get_pure_location (aaa_eq_bbb));
kono
parents: 68
diff changeset
1870 ASSERT_EQ (c12, get_start (aaa_eq_bbb));
kono
parents: 68
diff changeset
1871 ASSERT_FALSE (IS_ADHOC_LOC (get_start (aaa_eq_bbb)));
kono
parents: 68
diff changeset
1872 ASSERT_EQ (c21, get_finish (aaa_eq_bbb));
kono
parents: 68
diff changeset
1873 ASSERT_FALSE (IS_ADHOC_LOC (get_finish (aaa_eq_bbb)));
kono
parents: 68
diff changeset
1874 const location_t not_aaa_eq_bbb = make_location (c11, c12, aaa_eq_bbb);
kono
parents: 68
diff changeset
1875 /* It should use the finish location of the range, not store the range
kono
parents: 68
diff changeset
1876 itself. */
kono
parents: 68
diff changeset
1877 ASSERT_EQ (c11, get_pure_location (not_aaa_eq_bbb));
kono
parents: 68
diff changeset
1878 ASSERT_EQ (c12, get_start (not_aaa_eq_bbb));
kono
parents: 68
diff changeset
1879 ASSERT_FALSE (IS_ADHOC_LOC (get_start (not_aaa_eq_bbb)));
kono
parents: 68
diff changeset
1880 ASSERT_EQ (c21, get_finish (not_aaa_eq_bbb));
kono
parents: 68
diff changeset
1881 ASSERT_FALSE (IS_ADHOC_LOC (get_finish (not_aaa_eq_bbb)));
kono
parents: 68
diff changeset
1882 }
kono
parents: 68
diff changeset
1883
kono
parents: 68
diff changeset
1884 /* Verify reading of input files (e.g. for caret-based diagnostics). */
kono
parents: 68
diff changeset
1885
kono
parents: 68
diff changeset
1886 static void
kono
parents: 68
diff changeset
1887 test_reading_source_line ()
kono
parents: 68
diff changeset
1888 {
kono
parents: 68
diff changeset
1889 /* Create a tempfile and write some text to it. */
kono
parents: 68
diff changeset
1890 temp_source_file tmp (SELFTEST_LOCATION, ".txt",
kono
parents: 68
diff changeset
1891 "01234567890123456789\n"
kono
parents: 68
diff changeset
1892 "This is the test text\n"
kono
parents: 68
diff changeset
1893 "This is the 3rd line");
kono
parents: 68
diff changeset
1894
kono
parents: 68
diff changeset
1895 /* Read back a specific line from the tempfile. */
kono
parents: 68
diff changeset
1896 int line_size;
kono
parents: 68
diff changeset
1897 const char *source_line = location_get_source_line (tmp.get_filename (),
kono
parents: 68
diff changeset
1898 3, &line_size);
kono
parents: 68
diff changeset
1899 ASSERT_TRUE (source_line != NULL);
kono
parents: 68
diff changeset
1900 ASSERT_EQ (20, line_size);
kono
parents: 68
diff changeset
1901 ASSERT_TRUE (!strncmp ("This is the 3rd line",
kono
parents: 68
diff changeset
1902 source_line, line_size));
kono
parents: 68
diff changeset
1903
kono
parents: 68
diff changeset
1904 source_line = location_get_source_line (tmp.get_filename (),
kono
parents: 68
diff changeset
1905 2, &line_size);
kono
parents: 68
diff changeset
1906 ASSERT_TRUE (source_line != NULL);
kono
parents: 68
diff changeset
1907 ASSERT_EQ (21, line_size);
kono
parents: 68
diff changeset
1908 ASSERT_TRUE (!strncmp ("This is the test text",
kono
parents: 68
diff changeset
1909 source_line, line_size));
kono
parents: 68
diff changeset
1910
kono
parents: 68
diff changeset
1911 source_line = location_get_source_line (tmp.get_filename (),
kono
parents: 68
diff changeset
1912 4, &line_size);
kono
parents: 68
diff changeset
1913 ASSERT_TRUE (source_line == NULL);
kono
parents: 68
diff changeset
1914 }
kono
parents: 68
diff changeset
1915
kono
parents: 68
diff changeset
1916 /* Tests of lexing. */
kono
parents: 68
diff changeset
1917
kono
parents: 68
diff changeset
1918 /* Verify that token TOK from PARSER has cpp_token_as_text
kono
parents: 68
diff changeset
1919 equal to EXPECTED_TEXT. */
kono
parents: 68
diff changeset
1920
kono
parents: 68
diff changeset
1921 #define ASSERT_TOKEN_AS_TEXT_EQ(PARSER, TOK, EXPECTED_TEXT) \
kono
parents: 68
diff changeset
1922 SELFTEST_BEGIN_STMT \
kono
parents: 68
diff changeset
1923 unsigned char *actual_txt = cpp_token_as_text ((PARSER), (TOK)); \
kono
parents: 68
diff changeset
1924 ASSERT_STREQ ((EXPECTED_TEXT), (const char *)actual_txt); \
kono
parents: 68
diff changeset
1925 SELFTEST_END_STMT
kono
parents: 68
diff changeset
1926
kono
parents: 68
diff changeset
1927 /* Verify that TOK's src_loc is within EXP_FILENAME at EXP_LINENUM,
kono
parents: 68
diff changeset
1928 and ranges from EXP_START_COL to EXP_FINISH_COL.
kono
parents: 68
diff changeset
1929 Use LOC as the effective location of the selftest. */
kono
parents: 68
diff changeset
1930
kono
parents: 68
diff changeset
1931 static void
kono
parents: 68
diff changeset
1932 assert_token_loc_eq (const location &loc,
kono
parents: 68
diff changeset
1933 const cpp_token *tok,
kono
parents: 68
diff changeset
1934 const char *exp_filename, int exp_linenum,
kono
parents: 68
diff changeset
1935 int exp_start_col, int exp_finish_col)
kono
parents: 68
diff changeset
1936 {
kono
parents: 68
diff changeset
1937 location_t tok_loc = tok->src_loc;
kono
parents: 68
diff changeset
1938 ASSERT_STREQ_AT (loc, exp_filename, LOCATION_FILE (tok_loc));
kono
parents: 68
diff changeset
1939 ASSERT_EQ_AT (loc, exp_linenum, LOCATION_LINE (tok_loc));
kono
parents: 68
diff changeset
1940
kono
parents: 68
diff changeset
1941 /* If location_t values are sufficiently high, then column numbers
kono
parents: 68
diff changeset
1942 will be unavailable. */
kono
parents: 68
diff changeset
1943 if (!should_have_column_data_p (tok_loc))
kono
parents: 68
diff changeset
1944 return;
kono
parents: 68
diff changeset
1945
kono
parents: 68
diff changeset
1946 ASSERT_EQ_AT (loc, exp_start_col, LOCATION_COLUMN (tok_loc));
kono
parents: 68
diff changeset
1947 source_range tok_range = get_range_from_loc (line_table, tok_loc);
kono
parents: 68
diff changeset
1948 ASSERT_EQ_AT (loc, exp_start_col, LOCATION_COLUMN (tok_range.m_start));
kono
parents: 68
diff changeset
1949 ASSERT_EQ_AT (loc, exp_finish_col, LOCATION_COLUMN (tok_range.m_finish));
kono
parents: 68
diff changeset
1950 }
kono
parents: 68
diff changeset
1951
kono
parents: 68
diff changeset
1952 /* Use assert_token_loc_eq to verify the TOK->src_loc, using
kono
parents: 68
diff changeset
1953 SELFTEST_LOCATION as the effective location of the selftest. */
kono
parents: 68
diff changeset
1954
kono
parents: 68
diff changeset
1955 #define ASSERT_TOKEN_LOC_EQ(TOK, EXP_FILENAME, EXP_LINENUM, \
kono
parents: 68
diff changeset
1956 EXP_START_COL, EXP_FINISH_COL) \
kono
parents: 68
diff changeset
1957 assert_token_loc_eq (SELFTEST_LOCATION, (TOK), (EXP_FILENAME), \
kono
parents: 68
diff changeset
1958 (EXP_LINENUM), (EXP_START_COL), (EXP_FINISH_COL))
kono
parents: 68
diff changeset
1959
kono
parents: 68
diff changeset
1960 /* Test of lexing a file using libcpp, verifying tokens and their
kono
parents: 68
diff changeset
1961 location information. */
kono
parents: 68
diff changeset
1962
kono
parents: 68
diff changeset
1963 static void
kono
parents: 68
diff changeset
1964 test_lexer (const line_table_case &case_)
kono
parents: 68
diff changeset
1965 {
kono
parents: 68
diff changeset
1966 /* Create a tempfile and write some text to it. */
kono
parents: 68
diff changeset
1967 const char *content =
kono
parents: 68
diff changeset
1968 /*00000000011111111112222222222333333.3333444444444.455555555556
kono
parents: 68
diff changeset
1969 12345678901234567890123456789012345.6789012345678.901234567890. */
kono
parents: 68
diff changeset
1970 ("test_name /* c-style comment */\n"
kono
parents: 68
diff changeset
1971 " \"test literal\"\n"
kono
parents: 68
diff changeset
1972 " // test c++-style comment\n"
kono
parents: 68
diff changeset
1973 " 42\n");
kono
parents: 68
diff changeset
1974 temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
kono
parents: 68
diff changeset
1975
kono
parents: 68
diff changeset
1976 line_table_test ltt (case_);
kono
parents: 68
diff changeset
1977
kono
parents: 68
diff changeset
1978 cpp_reader *parser = cpp_create_reader (CLK_GNUC89, NULL, line_table);
kono
parents: 68
diff changeset
1979
kono
parents: 68
diff changeset
1980 const char *fname = cpp_read_main_file (parser, tmp.get_filename ());
kono
parents: 68
diff changeset
1981 ASSERT_NE (fname, NULL);
kono
parents: 68
diff changeset
1982
kono
parents: 68
diff changeset
1983 /* Verify that we get the expected tokens back, with the correct
kono
parents: 68
diff changeset
1984 location information. */
kono
parents: 68
diff changeset
1985
kono
parents: 68
diff changeset
1986 location_t loc;
kono
parents: 68
diff changeset
1987 const cpp_token *tok;
kono
parents: 68
diff changeset
1988 tok = cpp_get_token_with_location (parser, &loc);
kono
parents: 68
diff changeset
1989 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
1990 ASSERT_EQ (tok->type, CPP_NAME);
kono
parents: 68
diff changeset
1991 ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "test_name");
kono
parents: 68
diff changeset
1992 ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 1, 1, 9);
kono
parents: 68
diff changeset
1993
kono
parents: 68
diff changeset
1994 tok = cpp_get_token_with_location (parser, &loc);
kono
parents: 68
diff changeset
1995 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
1996 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
1997 ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "\"test literal\"");
kono
parents: 68
diff changeset
1998 ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 2, 35, 48);
kono
parents: 68
diff changeset
1999
kono
parents: 68
diff changeset
2000 tok = cpp_get_token_with_location (parser, &loc);
kono
parents: 68
diff changeset
2001 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
2002 ASSERT_EQ (tok->type, CPP_NUMBER);
kono
parents: 68
diff changeset
2003 ASSERT_TOKEN_AS_TEXT_EQ (parser, tok, "42");
kono
parents: 68
diff changeset
2004 ASSERT_TOKEN_LOC_EQ (tok, tmp.get_filename (), 4, 4, 5);
kono
parents: 68
diff changeset
2005
kono
parents: 68
diff changeset
2006 tok = cpp_get_token_with_location (parser, &loc);
kono
parents: 68
diff changeset
2007 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
2008 ASSERT_EQ (tok->type, CPP_EOF);
kono
parents: 68
diff changeset
2009
kono
parents: 68
diff changeset
2010 cpp_finish (parser, NULL);
kono
parents: 68
diff changeset
2011 cpp_destroy (parser);
kono
parents: 68
diff changeset
2012 }
kono
parents: 68
diff changeset
2013
kono
parents: 68
diff changeset
2014 /* Forward decls. */
kono
parents: 68
diff changeset
2015
kono
parents: 68
diff changeset
2016 struct lexer_test;
kono
parents: 68
diff changeset
2017 class lexer_test_options;
kono
parents: 68
diff changeset
2018
kono
parents: 68
diff changeset
2019 /* A class for specifying options of a lexer_test.
kono
parents: 68
diff changeset
2020 The "apply" vfunc is called during the lexer_test constructor. */
kono
parents: 68
diff changeset
2021
kono
parents: 68
diff changeset
2022 class lexer_test_options
kono
parents: 68
diff changeset
2023 {
kono
parents: 68
diff changeset
2024 public:
kono
parents: 68
diff changeset
2025 virtual void apply (lexer_test &) = 0;
kono
parents: 68
diff changeset
2026 };
kono
parents: 68
diff changeset
2027
kono
parents: 68
diff changeset
2028 /* Wrapper around an cpp_reader *, which calls cpp_finish and cpp_destroy
kono
parents: 68
diff changeset
2029 in its dtor.
kono
parents: 68
diff changeset
2030
kono
parents: 68
diff changeset
2031 This is needed by struct lexer_test to ensure that the cleanup of the
kono
parents: 68
diff changeset
2032 cpp_reader happens *after* the cleanup of the temp_source_file. */
kono
parents: 68
diff changeset
2033
kono
parents: 68
diff changeset
2034 class cpp_reader_ptr
kono
parents: 68
diff changeset
2035 {
kono
parents: 68
diff changeset
2036 public:
kono
parents: 68
diff changeset
2037 cpp_reader_ptr (cpp_reader *ptr) : m_ptr (ptr) {}
kono
parents: 68
diff changeset
2038
kono
parents: 68
diff changeset
2039 ~cpp_reader_ptr ()
kono
parents: 68
diff changeset
2040 {
kono
parents: 68
diff changeset
2041 cpp_finish (m_ptr, NULL);
kono
parents: 68
diff changeset
2042 cpp_destroy (m_ptr);
kono
parents: 68
diff changeset
2043 }
kono
parents: 68
diff changeset
2044
kono
parents: 68
diff changeset
2045 operator cpp_reader * () const { return m_ptr; }
kono
parents: 68
diff changeset
2046
kono
parents: 68
diff changeset
2047 private:
kono
parents: 68
diff changeset
2048 cpp_reader *m_ptr;
kono
parents: 68
diff changeset
2049 };
kono
parents: 68
diff changeset
2050
kono
parents: 68
diff changeset
2051 /* A struct for writing lexer tests. */
kono
parents: 68
diff changeset
2052
kono
parents: 68
diff changeset
2053 struct lexer_test
kono
parents: 68
diff changeset
2054 {
kono
parents: 68
diff changeset
2055 lexer_test (const line_table_case &case_, const char *content,
kono
parents: 68
diff changeset
2056 lexer_test_options *options);
kono
parents: 68
diff changeset
2057 ~lexer_test ();
kono
parents: 68
diff changeset
2058
kono
parents: 68
diff changeset
2059 const cpp_token *get_token ();
kono
parents: 68
diff changeset
2060
kono
parents: 68
diff changeset
2061 /* The ordering of these fields matters.
kono
parents: 68
diff changeset
2062 The line_table_test must be first, since the cpp_reader_ptr
kono
parents: 68
diff changeset
2063 uses it.
kono
parents: 68
diff changeset
2064 The cpp_reader must be cleaned up *after* the temp_source_file
kono
parents: 68
diff changeset
2065 since the filenames in input.c's input cache are owned by the
kono
parents: 68
diff changeset
2066 cpp_reader; in particular, when ~temp_source_file evicts the
kono
parents: 68
diff changeset
2067 filename the filenames must still be alive. */
kono
parents: 68
diff changeset
2068 line_table_test m_ltt;
kono
parents: 68
diff changeset
2069 cpp_reader_ptr m_parser;
kono
parents: 68
diff changeset
2070 temp_source_file m_tempfile;
kono
parents: 68
diff changeset
2071 string_concat_db m_concats;
kono
parents: 68
diff changeset
2072 bool m_implicitly_expect_EOF;
kono
parents: 68
diff changeset
2073 };
kono
parents: 68
diff changeset
2074
kono
parents: 68
diff changeset
2075 /* Use an EBCDIC encoding for the execution charset, specifically
kono
parents: 68
diff changeset
2076 IBM1047-encoded (aka "EBCDIC 1047", or "Code page 1047").
kono
parents: 68
diff changeset
2077
kono
parents: 68
diff changeset
2078 This exercises iconv integration within libcpp.
kono
parents: 68
diff changeset
2079 Not every build of iconv supports the given charset,
kono
parents: 68
diff changeset
2080 so we need to flag this error and handle it gracefully. */
kono
parents: 68
diff changeset
2081
kono
parents: 68
diff changeset
2082 class ebcdic_execution_charset : public lexer_test_options
kono
parents: 68
diff changeset
2083 {
kono
parents: 68
diff changeset
2084 public:
kono
parents: 68
diff changeset
2085 ebcdic_execution_charset () : m_num_iconv_errors (0)
kono
parents: 68
diff changeset
2086 {
kono
parents: 68
diff changeset
2087 gcc_assert (s_singleton == NULL);
kono
parents: 68
diff changeset
2088 s_singleton = this;
kono
parents: 68
diff changeset
2089 }
kono
parents: 68
diff changeset
2090 ~ebcdic_execution_charset ()
kono
parents: 68
diff changeset
2091 {
kono
parents: 68
diff changeset
2092 gcc_assert (s_singleton == this);
kono
parents: 68
diff changeset
2093 s_singleton = NULL;
kono
parents: 68
diff changeset
2094 }
kono
parents: 68
diff changeset
2095
kono
parents: 68
diff changeset
2096 void apply (lexer_test &test) FINAL OVERRIDE
kono
parents: 68
diff changeset
2097 {
kono
parents: 68
diff changeset
2098 cpp_options *cpp_opts = cpp_get_options (test.m_parser);
kono
parents: 68
diff changeset
2099 cpp_opts->narrow_charset = "IBM1047";
kono
parents: 68
diff changeset
2100
kono
parents: 68
diff changeset
2101 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
kono
parents: 68
diff changeset
2102 callbacks->error = on_error;
kono
parents: 68
diff changeset
2103 }
kono
parents: 68
diff changeset
2104
kono
parents: 68
diff changeset
2105 static bool on_error (cpp_reader *pfile ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2106 int level ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2107 int reason ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2108 rich_location *richloc ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2109 const char *msgid, va_list *ap ATTRIBUTE_UNUSED)
kono
parents: 68
diff changeset
2110 ATTRIBUTE_FPTR_PRINTF(5,0)
kono
parents: 68
diff changeset
2111 {
kono
parents: 68
diff changeset
2112 gcc_assert (s_singleton);
kono
parents: 68
diff changeset
2113 /* Avoid exgettext from picking this up, it is translated in libcpp. */
kono
parents: 68
diff changeset
2114 const char *msg = "conversion from %s to %s not supported by iconv";
kono
parents: 68
diff changeset
2115 #ifdef ENABLE_NLS
kono
parents: 68
diff changeset
2116 msg = dgettext ("cpplib", msg);
kono
parents: 68
diff changeset
2117 #endif
kono
parents: 68
diff changeset
2118 /* Detect and record errors emitted by libcpp/charset.c:init_iconv_desc
kono
parents: 68
diff changeset
2119 when the local iconv build doesn't support the conversion. */
kono
parents: 68
diff changeset
2120 if (strcmp (msgid, msg) == 0)
kono
parents: 68
diff changeset
2121 {
kono
parents: 68
diff changeset
2122 s_singleton->m_num_iconv_errors++;
kono
parents: 68
diff changeset
2123 return true;
kono
parents: 68
diff changeset
2124 }
kono
parents: 68
diff changeset
2125
kono
parents: 68
diff changeset
2126 /* Otherwise, we have an unexpected error. */
kono
parents: 68
diff changeset
2127 abort ();
kono
parents: 68
diff changeset
2128 }
kono
parents: 68
diff changeset
2129
kono
parents: 68
diff changeset
2130 bool iconv_errors_occurred_p () const { return m_num_iconv_errors > 0; }
kono
parents: 68
diff changeset
2131
kono
parents: 68
diff changeset
2132 private:
kono
parents: 68
diff changeset
2133 static ebcdic_execution_charset *s_singleton;
kono
parents: 68
diff changeset
2134 int m_num_iconv_errors;
kono
parents: 68
diff changeset
2135 };
kono
parents: 68
diff changeset
2136
kono
parents: 68
diff changeset
2137 ebcdic_execution_charset *ebcdic_execution_charset::s_singleton;
kono
parents: 68
diff changeset
2138
kono
parents: 68
diff changeset
2139 /* A lexer_test_options subclass that records a list of error
kono
parents: 68
diff changeset
2140 messages emitted by the lexer. */
kono
parents: 68
diff changeset
2141
kono
parents: 68
diff changeset
2142 class lexer_error_sink : public lexer_test_options
kono
parents: 68
diff changeset
2143 {
kono
parents: 68
diff changeset
2144 public:
kono
parents: 68
diff changeset
2145 lexer_error_sink ()
kono
parents: 68
diff changeset
2146 {
kono
parents: 68
diff changeset
2147 gcc_assert (s_singleton == NULL);
kono
parents: 68
diff changeset
2148 s_singleton = this;
kono
parents: 68
diff changeset
2149 }
kono
parents: 68
diff changeset
2150 ~lexer_error_sink ()
kono
parents: 68
diff changeset
2151 {
kono
parents: 68
diff changeset
2152 gcc_assert (s_singleton == this);
kono
parents: 68
diff changeset
2153 s_singleton = NULL;
kono
parents: 68
diff changeset
2154
kono
parents: 68
diff changeset
2155 int i;
kono
parents: 68
diff changeset
2156 char *str;
kono
parents: 68
diff changeset
2157 FOR_EACH_VEC_ELT (m_errors, i, str)
kono
parents: 68
diff changeset
2158 free (str);
kono
parents: 68
diff changeset
2159 }
kono
parents: 68
diff changeset
2160
kono
parents: 68
diff changeset
2161 void apply (lexer_test &test) FINAL OVERRIDE
kono
parents: 68
diff changeset
2162 {
kono
parents: 68
diff changeset
2163 cpp_callbacks *callbacks = cpp_get_callbacks (test.m_parser);
kono
parents: 68
diff changeset
2164 callbacks->error = on_error;
kono
parents: 68
diff changeset
2165 }
kono
parents: 68
diff changeset
2166
kono
parents: 68
diff changeset
2167 static bool on_error (cpp_reader *pfile ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2168 int level ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2169 int reason ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2170 rich_location *richloc ATTRIBUTE_UNUSED,
kono
parents: 68
diff changeset
2171 const char *msgid, va_list *ap)
kono
parents: 68
diff changeset
2172 ATTRIBUTE_FPTR_PRINTF(5,0)
kono
parents: 68
diff changeset
2173 {
kono
parents: 68
diff changeset
2174 char *msg = xvasprintf (msgid, *ap);
kono
parents: 68
diff changeset
2175 s_singleton->m_errors.safe_push (msg);
kono
parents: 68
diff changeset
2176 return true;
kono
parents: 68
diff changeset
2177 }
kono
parents: 68
diff changeset
2178
kono
parents: 68
diff changeset
2179 auto_vec<char *> m_errors;
kono
parents: 68
diff changeset
2180
kono
parents: 68
diff changeset
2181 private:
kono
parents: 68
diff changeset
2182 static lexer_error_sink *s_singleton;
kono
parents: 68
diff changeset
2183 };
kono
parents: 68
diff changeset
2184
kono
parents: 68
diff changeset
2185 lexer_error_sink *lexer_error_sink::s_singleton;
kono
parents: 68
diff changeset
2186
kono
parents: 68
diff changeset
2187 /* Constructor. Override line_table with a new instance based on CASE_,
kono
parents: 68
diff changeset
2188 and write CONTENT to a tempfile. Create a cpp_reader, and use it to
kono
parents: 68
diff changeset
2189 start parsing the tempfile. */
kono
parents: 68
diff changeset
2190
kono
parents: 68
diff changeset
2191 lexer_test::lexer_test (const line_table_case &case_, const char *content,
kono
parents: 68
diff changeset
2192 lexer_test_options *options)
kono
parents: 68
diff changeset
2193 : m_ltt (case_),
kono
parents: 68
diff changeset
2194 m_parser (cpp_create_reader (CLK_GNUC99, NULL, line_table)),
kono
parents: 68
diff changeset
2195 /* Create a tempfile and write the text to it. */
kono
parents: 68
diff changeset
2196 m_tempfile (SELFTEST_LOCATION, ".c", content),
kono
parents: 68
diff changeset
2197 m_concats (),
kono
parents: 68
diff changeset
2198 m_implicitly_expect_EOF (true)
kono
parents: 68
diff changeset
2199 {
kono
parents: 68
diff changeset
2200 if (options)
kono
parents: 68
diff changeset
2201 options->apply (*this);
kono
parents: 68
diff changeset
2202
kono
parents: 68
diff changeset
2203 cpp_init_iconv (m_parser);
kono
parents: 68
diff changeset
2204
kono
parents: 68
diff changeset
2205 /* Parse the file. */
kono
parents: 68
diff changeset
2206 const char *fname = cpp_read_main_file (m_parser,
kono
parents: 68
diff changeset
2207 m_tempfile.get_filename ());
kono
parents: 68
diff changeset
2208 ASSERT_NE (fname, NULL);
kono
parents: 68
diff changeset
2209 }
kono
parents: 68
diff changeset
2210
kono
parents: 68
diff changeset
2211 /* Destructor. By default, verify that the next token in m_parser is EOF. */
kono
parents: 68
diff changeset
2212
kono
parents: 68
diff changeset
2213 lexer_test::~lexer_test ()
kono
parents: 68
diff changeset
2214 {
kono
parents: 68
diff changeset
2215 location_t loc;
kono
parents: 68
diff changeset
2216 const cpp_token *tok;
kono
parents: 68
diff changeset
2217
kono
parents: 68
diff changeset
2218 if (m_implicitly_expect_EOF)
kono
parents: 68
diff changeset
2219 {
kono
parents: 68
diff changeset
2220 tok = cpp_get_token_with_location (m_parser, &loc);
kono
parents: 68
diff changeset
2221 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
2222 ASSERT_EQ (tok->type, CPP_EOF);
kono
parents: 68
diff changeset
2223 }
kono
parents: 68
diff changeset
2224 }
kono
parents: 68
diff changeset
2225
kono
parents: 68
diff changeset
2226 /* Get the next token from m_parser. */
kono
parents: 68
diff changeset
2227
kono
parents: 68
diff changeset
2228 const cpp_token *
kono
parents: 68
diff changeset
2229 lexer_test::get_token ()
kono
parents: 68
diff changeset
2230 {
kono
parents: 68
diff changeset
2231 location_t loc;
kono
parents: 68
diff changeset
2232 const cpp_token *tok;
kono
parents: 68
diff changeset
2233
kono
parents: 68
diff changeset
2234 tok = cpp_get_token_with_location (m_parser, &loc);
kono
parents: 68
diff changeset
2235 ASSERT_NE (tok, NULL);
kono
parents: 68
diff changeset
2236 return tok;
kono
parents: 68
diff changeset
2237 }
kono
parents: 68
diff changeset
2238
kono
parents: 68
diff changeset
2239 /* Verify that locations within string literals are correctly handled. */
kono
parents: 68
diff changeset
2240
kono
parents: 68
diff changeset
2241 /* Verify get_source_range_for_substring for token(s) at STRLOC,
kono
parents: 68
diff changeset
2242 using the string concatenation database for TEST.
kono
parents: 68
diff changeset
2243
kono
parents: 68
diff changeset
2244 Assert that the character at index IDX is on EXPECTED_LINE,
kono
parents: 68
diff changeset
2245 and that it begins at column EXPECTED_START_COL and ends at
kono
parents: 68
diff changeset
2246 EXPECTED_FINISH_COL (unless the locations are beyond
kono
parents: 68
diff changeset
2247 LINE_MAP_MAX_LOCATION_WITH_COLS, in which case don't check their
kono
parents: 68
diff changeset
2248 columns). */
kono
parents: 68
diff changeset
2249
kono
parents: 68
diff changeset
2250 static void
kono
parents: 68
diff changeset
2251 assert_char_at_range (const location &loc,
kono
parents: 68
diff changeset
2252 lexer_test& test,
kono
parents: 68
diff changeset
2253 location_t strloc, enum cpp_ttype type, int idx,
kono
parents: 68
diff changeset
2254 int expected_line, int expected_start_col,
kono
parents: 68
diff changeset
2255 int expected_finish_col)
kono
parents: 68
diff changeset
2256 {
kono
parents: 68
diff changeset
2257 cpp_reader *pfile = test.m_parser;
kono
parents: 68
diff changeset
2258 string_concat_db *concats = &test.m_concats;
kono
parents: 68
diff changeset
2259
kono
parents: 68
diff changeset
2260 source_range actual_range = source_range();
kono
parents: 68
diff changeset
2261 const char *err
kono
parents: 68
diff changeset
2262 = get_source_range_for_char (pfile, concats, strloc, type, idx,
kono
parents: 68
diff changeset
2263 &actual_range);
kono
parents: 68
diff changeset
2264 if (should_have_column_data_p (strloc))
kono
parents: 68
diff changeset
2265 ASSERT_EQ_AT (loc, NULL, err);
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2266 else
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2267 {
111
kono
parents: 68
diff changeset
2268 ASSERT_STREQ_AT (loc,
kono
parents: 68
diff changeset
2269 "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
kono
parents: 68
diff changeset
2270 err);
kono
parents: 68
diff changeset
2271 return;
kono
parents: 68
diff changeset
2272 }
kono
parents: 68
diff changeset
2273
kono
parents: 68
diff changeset
2274 int actual_start_line = LOCATION_LINE (actual_range.m_start);
kono
parents: 68
diff changeset
2275 ASSERT_EQ_AT (loc, expected_line, actual_start_line);
kono
parents: 68
diff changeset
2276 int actual_finish_line = LOCATION_LINE (actual_range.m_finish);
kono
parents: 68
diff changeset
2277 ASSERT_EQ_AT (loc, expected_line, actual_finish_line);
kono
parents: 68
diff changeset
2278
kono
parents: 68
diff changeset
2279 if (should_have_column_data_p (actual_range.m_start))
kono
parents: 68
diff changeset
2280 {
kono
parents: 68
diff changeset
2281 int actual_start_col = LOCATION_COLUMN (actual_range.m_start);
kono
parents: 68
diff changeset
2282 ASSERT_EQ_AT (loc, expected_start_col, actual_start_col);
kono
parents: 68
diff changeset
2283 }
kono
parents: 68
diff changeset
2284 if (should_have_column_data_p (actual_range.m_finish))
kono
parents: 68
diff changeset
2285 {
kono
parents: 68
diff changeset
2286 int actual_finish_col = LOCATION_COLUMN (actual_range.m_finish);
kono
parents: 68
diff changeset
2287 ASSERT_EQ_AT (loc, expected_finish_col, actual_finish_col);
kono
parents: 68
diff changeset
2288 }
kono
parents: 68
diff changeset
2289 }
kono
parents: 68
diff changeset
2290
kono
parents: 68
diff changeset
2291 /* Macro for calling assert_char_at_range, supplying SELFTEST_LOCATION for
kono
parents: 68
diff changeset
2292 the effective location of any errors. */
kono
parents: 68
diff changeset
2293
kono
parents: 68
diff changeset
2294 #define ASSERT_CHAR_AT_RANGE(LEXER_TEST, STRLOC, TYPE, IDX, EXPECTED_LINE, \
kono
parents: 68
diff changeset
2295 EXPECTED_START_COL, EXPECTED_FINISH_COL) \
kono
parents: 68
diff changeset
2296 assert_char_at_range (SELFTEST_LOCATION, (LEXER_TEST), (STRLOC), (TYPE), \
kono
parents: 68
diff changeset
2297 (IDX), (EXPECTED_LINE), (EXPECTED_START_COL), \
kono
parents: 68
diff changeset
2298 (EXPECTED_FINISH_COL))
kono
parents: 68
diff changeset
2299
kono
parents: 68
diff changeset
2300 /* Verify get_num_source_ranges_for_substring for token(s) at STRLOC,
kono
parents: 68
diff changeset
2301 using the string concatenation database for TEST.
kono
parents: 68
diff changeset
2302
kono
parents: 68
diff changeset
2303 Assert that the token(s) at STRLOC contain EXPECTED_NUM_RANGES. */
kono
parents: 68
diff changeset
2304
kono
parents: 68
diff changeset
2305 static void
kono
parents: 68
diff changeset
2306 assert_num_substring_ranges (const location &loc,
kono
parents: 68
diff changeset
2307 lexer_test& test,
kono
parents: 68
diff changeset
2308 location_t strloc,
kono
parents: 68
diff changeset
2309 enum cpp_ttype type,
kono
parents: 68
diff changeset
2310 int expected_num_ranges)
kono
parents: 68
diff changeset
2311 {
kono
parents: 68
diff changeset
2312 cpp_reader *pfile = test.m_parser;
kono
parents: 68
diff changeset
2313 string_concat_db *concats = &test.m_concats;
kono
parents: 68
diff changeset
2314
kono
parents: 68
diff changeset
2315 int actual_num_ranges = -1;
kono
parents: 68
diff changeset
2316 const char *err
kono
parents: 68
diff changeset
2317 = get_num_source_ranges_for_substring (pfile, concats, strloc, type,
kono
parents: 68
diff changeset
2318 &actual_num_ranges);
kono
parents: 68
diff changeset
2319 if (should_have_column_data_p (strloc))
kono
parents: 68
diff changeset
2320 ASSERT_EQ_AT (loc, NULL, err);
kono
parents: 68
diff changeset
2321 else
kono
parents: 68
diff changeset
2322 {
kono
parents: 68
diff changeset
2323 ASSERT_STREQ_AT (loc,
kono
parents: 68
diff changeset
2324 "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
kono
parents: 68
diff changeset
2325 err);
kono
parents: 68
diff changeset
2326 return;
kono
parents: 68
diff changeset
2327 }
kono
parents: 68
diff changeset
2328 ASSERT_EQ_AT (loc, expected_num_ranges, actual_num_ranges);
kono
parents: 68
diff changeset
2329 }
kono
parents: 68
diff changeset
2330
kono
parents: 68
diff changeset
2331 /* Macro for calling assert_num_substring_ranges, supplying
kono
parents: 68
diff changeset
2332 SELFTEST_LOCATION for the effective location of any errors. */
kono
parents: 68
diff changeset
2333
kono
parents: 68
diff changeset
2334 #define ASSERT_NUM_SUBSTRING_RANGES(LEXER_TEST, STRLOC, TYPE, \
kono
parents: 68
diff changeset
2335 EXPECTED_NUM_RANGES) \
kono
parents: 68
diff changeset
2336 assert_num_substring_ranges (SELFTEST_LOCATION, (LEXER_TEST), (STRLOC), \
kono
parents: 68
diff changeset
2337 (TYPE), (EXPECTED_NUM_RANGES))
kono
parents: 68
diff changeset
2338
kono
parents: 68
diff changeset
2339
kono
parents: 68
diff changeset
2340 /* Verify that get_num_source_ranges_for_substring for token(s) at STRLOC
kono
parents: 68
diff changeset
2341 returns an error (using the string concatenation database for TEST). */
kono
parents: 68
diff changeset
2342
kono
parents: 68
diff changeset
2343 static void
kono
parents: 68
diff changeset
2344 assert_has_no_substring_ranges (const location &loc,
kono
parents: 68
diff changeset
2345 lexer_test& test,
kono
parents: 68
diff changeset
2346 location_t strloc,
kono
parents: 68
diff changeset
2347 enum cpp_ttype type,
kono
parents: 68
diff changeset
2348 const char *expected_err)
kono
parents: 68
diff changeset
2349 {
kono
parents: 68
diff changeset
2350 cpp_reader *pfile = test.m_parser;
kono
parents: 68
diff changeset
2351 string_concat_db *concats = &test.m_concats;
kono
parents: 68
diff changeset
2352 cpp_substring_ranges ranges;
kono
parents: 68
diff changeset
2353 const char *actual_err
kono
parents: 68
diff changeset
2354 = get_substring_ranges_for_loc (pfile, concats, strloc,
kono
parents: 68
diff changeset
2355 type, ranges);
kono
parents: 68
diff changeset
2356 if (should_have_column_data_p (strloc))
kono
parents: 68
diff changeset
2357 ASSERT_STREQ_AT (loc, expected_err, actual_err);
kono
parents: 68
diff changeset
2358 else
kono
parents: 68
diff changeset
2359 ASSERT_STREQ_AT (loc,
kono
parents: 68
diff changeset
2360 "range starts after LINE_MAP_MAX_LOCATION_WITH_COLS",
kono
parents: 68
diff changeset
2361 actual_err);
kono
parents: 68
diff changeset
2362 }
kono
parents: 68
diff changeset
2363
kono
parents: 68
diff changeset
2364 #define ASSERT_HAS_NO_SUBSTRING_RANGES(LEXER_TEST, STRLOC, TYPE, ERR) \
kono
parents: 68
diff changeset
2365 assert_has_no_substring_ranges (SELFTEST_LOCATION, (LEXER_TEST), \
kono
parents: 68
diff changeset
2366 (STRLOC), (TYPE), (ERR))
kono
parents: 68
diff changeset
2367
kono
parents: 68
diff changeset
2368 /* Lex a simple string literal. Verify the substring location data, before
kono
parents: 68
diff changeset
2369 and after running cpp_interpret_string on it. */
kono
parents: 68
diff changeset
2370
kono
parents: 68
diff changeset
2371 static void
kono
parents: 68
diff changeset
2372 test_lexer_string_locations_simple (const line_table_case &case_)
kono
parents: 68
diff changeset
2373 {
kono
parents: 68
diff changeset
2374 /* Digits 0-9 (with 0 at column 10), the simple way.
kono
parents: 68
diff changeset
2375 ....................000000000.11111111112.2222222223333333333
kono
parents: 68
diff changeset
2376 ....................123456789.01234567890.1234567890123456789
kono
parents: 68
diff changeset
2377 We add a trailing comment to ensure that we correctly locate
kono
parents: 68
diff changeset
2378 the end of the string literal token. */
kono
parents: 68
diff changeset
2379 const char *content = " \"0123456789\" /* not a string */\n";
kono
parents: 68
diff changeset
2380 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2381
kono
parents: 68
diff changeset
2382 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2383 location information. */
kono
parents: 68
diff changeset
2384 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2385 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2386 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
kono
parents: 68
diff changeset
2387 ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 20);
kono
parents: 68
diff changeset
2388
kono
parents: 68
diff changeset
2389 /* At this point in lexing, the quote characters are treated as part of
kono
parents: 68
diff changeset
2390 the string (they are stripped off by cpp_interpret_string). */
kono
parents: 68
diff changeset
2391
kono
parents: 68
diff changeset
2392 ASSERT_EQ (tok->val.str.len, 12);
kono
parents: 68
diff changeset
2393
kono
parents: 68
diff changeset
2394 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2395 cpp_string dst_string;
kono
parents: 68
diff changeset
2396 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2397 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2398 &dst_string, type);
kono
parents: 68
diff changeset
2399 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2400 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
2401 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2402
kono
parents: 68
diff changeset
2403 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2404 opening quote, but does include the closing quote. */
kono
parents: 68
diff changeset
2405 for (int i = 0; i <= 10; i++)
kono
parents: 68
diff changeset
2406 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1,
kono
parents: 68
diff changeset
2407 10 + i, 10 + i);
kono
parents: 68
diff changeset
2408
kono
parents: 68
diff changeset
2409 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
kono
parents: 68
diff changeset
2410 }
kono
parents: 68
diff changeset
2411
kono
parents: 68
diff changeset
2412 /* As test_lexer_string_locations_simple, but use an EBCDIC execution
kono
parents: 68
diff changeset
2413 encoding. */
kono
parents: 68
diff changeset
2414
kono
parents: 68
diff changeset
2415 static void
kono
parents: 68
diff changeset
2416 test_lexer_string_locations_ebcdic (const line_table_case &case_)
kono
parents: 68
diff changeset
2417 {
kono
parents: 68
diff changeset
2418 /* EBCDIC support requires iconv. */
kono
parents: 68
diff changeset
2419 if (!HAVE_ICONV)
kono
parents: 68
diff changeset
2420 return;
kono
parents: 68
diff changeset
2421
kono
parents: 68
diff changeset
2422 /* Digits 0-9 (with 0 at column 10), the simple way.
kono
parents: 68
diff changeset
2423 ....................000000000.11111111112.2222222223333333333
kono
parents: 68
diff changeset
2424 ....................123456789.01234567890.1234567890123456789
kono
parents: 68
diff changeset
2425 We add a trailing comment to ensure that we correctly locate
kono
parents: 68
diff changeset
2426 the end of the string literal token. */
kono
parents: 68
diff changeset
2427 const char *content = " \"0123456789\" /* not a string */\n";
kono
parents: 68
diff changeset
2428 ebcdic_execution_charset use_ebcdic;
kono
parents: 68
diff changeset
2429 lexer_test test (case_, content, &use_ebcdic);
kono
parents: 68
diff changeset
2430
kono
parents: 68
diff changeset
2431 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2432 location information. */
kono
parents: 68
diff changeset
2433 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2434 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2435 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
kono
parents: 68
diff changeset
2436 ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 20);
kono
parents: 68
diff changeset
2437
kono
parents: 68
diff changeset
2438 /* At this point in lexing, the quote characters are treated as part of
kono
parents: 68
diff changeset
2439 the string (they are stripped off by cpp_interpret_string). */
kono
parents: 68
diff changeset
2440
kono
parents: 68
diff changeset
2441 ASSERT_EQ (tok->val.str.len, 12);
kono
parents: 68
diff changeset
2442
kono
parents: 68
diff changeset
2443 /* The remainder of the test requires an iconv implementation that
kono
parents: 68
diff changeset
2444 can convert from UTF-8 to the EBCDIC encoding requested above. */
kono
parents: 68
diff changeset
2445 if (use_ebcdic.iconv_errors_occurred_p ())
kono
parents: 68
diff changeset
2446 return;
kono
parents: 68
diff changeset
2447
kono
parents: 68
diff changeset
2448 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2449 cpp_string dst_string;
kono
parents: 68
diff changeset
2450 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2451 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2452 &dst_string, type);
kono
parents: 68
diff changeset
2453 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2454 /* We should now have EBCDIC-encoded text, specifically
kono
parents: 68
diff changeset
2455 IBM1047-encoded (aka "EBCDIC 1047", or "Code page 1047").
kono
parents: 68
diff changeset
2456 The digits 0-9 are encoded as 240-249 i.e. 0xf0-0xf9. */
kono
parents: 68
diff changeset
2457 ASSERT_STREQ ("\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9",
kono
parents: 68
diff changeset
2458 (const char *)dst_string.text);
kono
parents: 68
diff changeset
2459 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2460
kono
parents: 68
diff changeset
2461 /* Verify that we don't attempt to record substring location information
kono
parents: 68
diff changeset
2462 for such cases. */
kono
parents: 68
diff changeset
2463 ASSERT_HAS_NO_SUBSTRING_RANGES
kono
parents: 68
diff changeset
2464 (test, tok->src_loc, type,
kono
parents: 68
diff changeset
2465 "execution character set != source character set");
kono
parents: 68
diff changeset
2466 }
kono
parents: 68
diff changeset
2467
kono
parents: 68
diff changeset
2468 /* Lex a string literal containing a hex-escaped character.
kono
parents: 68
diff changeset
2469 Verify the substring location data, before and after running
kono
parents: 68
diff changeset
2470 cpp_interpret_string on it. */
kono
parents: 68
diff changeset
2471
kono
parents: 68
diff changeset
2472 static void
kono
parents: 68
diff changeset
2473 test_lexer_string_locations_hex (const line_table_case &case_)
kono
parents: 68
diff changeset
2474 {
kono
parents: 68
diff changeset
2475 /* Digits 0-9, expressing digit 5 in ASCII as "\x35"
kono
parents: 68
diff changeset
2476 and with a space in place of digit 6, to terminate the escaped
kono
parents: 68
diff changeset
2477 hex code.
kono
parents: 68
diff changeset
2478 ....................000000000.111111.11112222.
kono
parents: 68
diff changeset
2479 ....................123456789.012345.67890123. */
kono
parents: 68
diff changeset
2480 const char *content = " \"01234\\x35 789\"\n";
kono
parents: 68
diff changeset
2481 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2482
kono
parents: 68
diff changeset
2483 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2484 location information. */
kono
parents: 68
diff changeset
2485 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2486 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2487 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\x35 789\"");
kono
parents: 68
diff changeset
2488 ASSERT_TOKEN_LOC_EQ (tok, test.m_tempfile.get_filename (), 1, 9, 23);
kono
parents: 68
diff changeset
2489
kono
parents: 68
diff changeset
2490 /* At this point in lexing, the quote characters are treated as part of
kono
parents: 68
diff changeset
2491 the string (they are stripped off by cpp_interpret_string). */
kono
parents: 68
diff changeset
2492 ASSERT_EQ (tok->val.str.len, 15);
kono
parents: 68
diff changeset
2493
kono
parents: 68
diff changeset
2494 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2495 cpp_string dst_string;
kono
parents: 68
diff changeset
2496 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2497 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2498 &dst_string, type);
kono
parents: 68
diff changeset
2499 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2500 ASSERT_STREQ ("012345 789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
2501 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2502
kono
parents: 68
diff changeset
2503 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2504 opening quote, but does include the closing quote. */
kono
parents: 68
diff changeset
2505 for (int i = 0; i <= 4; i++)
kono
parents: 68
diff changeset
2506 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2507 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 5, 1, 15, 18);
kono
parents: 68
diff changeset
2508 for (int i = 6; i <= 10; i++)
kono
parents: 68
diff changeset
2509 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 13 + i, 13 + i);
kono
parents: 68
diff changeset
2510
kono
parents: 68
diff changeset
2511 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
kono
parents: 68
diff changeset
2512 }
kono
parents: 68
diff changeset
2513
kono
parents: 68
diff changeset
2514 /* Lex a string literal containing an octal-escaped character.
kono
parents: 68
diff changeset
2515 Verify the substring location data after running cpp_interpret_string
kono
parents: 68
diff changeset
2516 on it. */
kono
parents: 68
diff changeset
2517
kono
parents: 68
diff changeset
2518 static void
kono
parents: 68
diff changeset
2519 test_lexer_string_locations_oct (const line_table_case &case_)
kono
parents: 68
diff changeset
2520 {
kono
parents: 68
diff changeset
2521 /* Digits 0-9, expressing digit 5 in ASCII as "\065"
kono
parents: 68
diff changeset
2522 and with a space in place of digit 6, to terminate the escaped
kono
parents: 68
diff changeset
2523 octal code.
kono
parents: 68
diff changeset
2524 ....................000000000.111111.11112222.2222223333333333444
kono
parents: 68
diff changeset
2525 ....................123456789.012345.67890123.4567890123456789012 */
kono
parents: 68
diff changeset
2526 const char *content = " \"01234\\065 789\" /* not a string */\n";
kono
parents: 68
diff changeset
2527 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2528
kono
parents: 68
diff changeset
2529 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2530 location information. */
kono
parents: 68
diff changeset
2531 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2532 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2533 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\065 789\"");
kono
parents: 68
diff changeset
2534
kono
parents: 68
diff changeset
2535 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2536 cpp_string dst_string;
kono
parents: 68
diff changeset
2537 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2538 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2539 &dst_string, type);
kono
parents: 68
diff changeset
2540 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2541 ASSERT_STREQ ("012345 789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
2542 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2543
kono
parents: 68
diff changeset
2544 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2545 opening quote, but does include the closing quote. */
kono
parents: 68
diff changeset
2546 for (int i = 0; i < 5; i++)
kono
parents: 68
diff changeset
2547 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2548 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 5, 1, 15, 18);
kono
parents: 68
diff changeset
2549 for (int i = 6; i <= 10; i++)
kono
parents: 68
diff changeset
2550 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 13 + i, 13 + i);
kono
parents: 68
diff changeset
2551
kono
parents: 68
diff changeset
2552 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 11);
kono
parents: 68
diff changeset
2553 }
kono
parents: 68
diff changeset
2554
kono
parents: 68
diff changeset
2555 /* Test of string literal containing letter escapes. */
kono
parents: 68
diff changeset
2556
kono
parents: 68
diff changeset
2557 static void
kono
parents: 68
diff changeset
2558 test_lexer_string_locations_letter_escape_1 (const line_table_case &case_)
kono
parents: 68
diff changeset
2559 {
kono
parents: 68
diff changeset
2560 /* The string "\tfoo\\\nbar" i.e. tab, "foo", backslash, newline, bar.
kono
parents: 68
diff changeset
2561 .....................000000000.1.11111.1.1.11222.22222223333333
kono
parents: 68
diff changeset
2562 .....................123456789.0.12345.6.7.89012.34567890123456. */
kono
parents: 68
diff changeset
2563 const char *content = (" \"\\tfoo\\\\\\nbar\" /* non-str */\n");
kono
parents: 68
diff changeset
2564 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2565
kono
parents: 68
diff changeset
2566 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
2567 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2568 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2569 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"\\tfoo\\\\\\nbar\"");
kono
parents: 68
diff changeset
2570
kono
parents: 68
diff changeset
2571 /* Verify ranges of individual characters. */
kono
parents: 68
diff changeset
2572 /* "\t". */
kono
parents: 68
diff changeset
2573 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2574 0, 1, 10, 11);
kono
parents: 68
diff changeset
2575 /* "foo". */
kono
parents: 68
diff changeset
2576 for (int i = 1; i <= 3; i++)
kono
parents: 68
diff changeset
2577 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2578 i, 1, 11 + i, 11 + i);
kono
parents: 68
diff changeset
2579 /* "\\" and "\n". */
kono
parents: 68
diff changeset
2580 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2581 4, 1, 15, 16);
kono
parents: 68
diff changeset
2582 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2583 5, 1, 17, 18);
kono
parents: 68
diff changeset
2584
kono
parents: 68
diff changeset
2585 /* "bar" and closing quote for nul-terminator. */
kono
parents: 68
diff changeset
2586 for (int i = 6; i <= 9; i++)
kono
parents: 68
diff changeset
2587 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2588 i, 1, 13 + i, 13 + i);
kono
parents: 68
diff changeset
2589
kono
parents: 68
diff changeset
2590 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 10);
kono
parents: 68
diff changeset
2591 }
kono
parents: 68
diff changeset
2592
kono
parents: 68
diff changeset
2593 /* Another test of a string literal containing a letter escape.
kono
parents: 68
diff changeset
2594 Based on string seen in
kono
parents: 68
diff changeset
2595 printf ("%-%\n");
kono
parents: 68
diff changeset
2596 in gcc.dg/format/c90-printf-1.c. */
kono
parents: 68
diff changeset
2597
kono
parents: 68
diff changeset
2598 static void
kono
parents: 68
diff changeset
2599 test_lexer_string_locations_letter_escape_2 (const line_table_case &case_)
kono
parents: 68
diff changeset
2600 {
kono
parents: 68
diff changeset
2601 /* .....................000000000.1111.11.1111.22222222223.
kono
parents: 68
diff changeset
2602 .....................123456789.0123.45.6789.01234567890. */
kono
parents: 68
diff changeset
2603 const char *content = (" \"%-%\\n\" /* non-str */\n");
kono
parents: 68
diff changeset
2604 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2605
kono
parents: 68
diff changeset
2606 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
2607 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2608 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2609 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"%-%\\n\"");
kono
parents: 68
diff changeset
2610
kono
parents: 68
diff changeset
2611 /* Verify ranges of individual characters. */
kono
parents: 68
diff changeset
2612 /* "%-%". */
kono
parents: 68
diff changeset
2613 for (int i = 0; i < 3; i++)
kono
parents: 68
diff changeset
2614 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2615 i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2616 /* "\n". */
kono
parents: 68
diff changeset
2617 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2618 3, 1, 13, 14);
kono
parents: 68
diff changeset
2619
kono
parents: 68
diff changeset
2620 /* Closing quote for nul-terminator. */
kono
parents: 68
diff changeset
2621 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
2622 4, 1, 15, 15);
kono
parents: 68
diff changeset
2623
kono
parents: 68
diff changeset
2624 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 5);
kono
parents: 68
diff changeset
2625 }
kono
parents: 68
diff changeset
2626
kono
parents: 68
diff changeset
2627 /* Lex a string literal containing UCN 4 characters.
kono
parents: 68
diff changeset
2628 Verify the substring location data after running cpp_interpret_string
kono
parents: 68
diff changeset
2629 on it. */
kono
parents: 68
diff changeset
2630
kono
parents: 68
diff changeset
2631 static void
kono
parents: 68
diff changeset
2632 test_lexer_string_locations_ucn4 (const line_table_case &case_)
kono
parents: 68
diff changeset
2633 {
kono
parents: 68
diff changeset
2634 /* Digits 0-9, expressing digits 5 and 6 as Roman numerals expressed
kono
parents: 68
diff changeset
2635 as UCN 4.
kono
parents: 68
diff changeset
2636 ....................000000000.111111.111122.222222223.33333333344444
kono
parents: 68
diff changeset
2637 ....................123456789.012345.678901.234567890.12345678901234 */
kono
parents: 68
diff changeset
2638 const char *content = " \"01234\\u2174\\u2175789\" /* non-str */\n";
kono
parents: 68
diff changeset
2639 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2640
kono
parents: 68
diff changeset
2641 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2642 location information. */
kono
parents: 68
diff changeset
2643 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2644 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2645 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"01234\\u2174\\u2175789\"");
kono
parents: 68
diff changeset
2646
kono
parents: 68
diff changeset
2647 /* Verify that cpp_interpret_string works.
kono
parents: 68
diff changeset
2648 The string should be encoded in the execution character
kono
parents: 68
diff changeset
2649 set. Assuming that that is UTF-8, we should have the following:
kono
parents: 68
diff changeset
2650 ----------- ---- ----- ------- ----------------
kono
parents: 68
diff changeset
2651 Byte offset Byte Octal Unicode Source Column(s)
kono
parents: 68
diff changeset
2652 ----------- ---- ----- ------- ----------------
kono
parents: 68
diff changeset
2653 0 0x30 '0' 10
kono
parents: 68
diff changeset
2654 1 0x31 '1' 11
kono
parents: 68
diff changeset
2655 2 0x32 '2' 12
kono
parents: 68
diff changeset
2656 3 0x33 '3' 13
kono
parents: 68
diff changeset
2657 4 0x34 '4' 14
kono
parents: 68
diff changeset
2658 5 0xE2 \342 U+2174 15-20
kono
parents: 68
diff changeset
2659 6 0x85 \205 (cont) 15-20
kono
parents: 68
diff changeset
2660 7 0xB4 \264 (cont) 15-20
kono
parents: 68
diff changeset
2661 8 0xE2 \342 U+2175 21-26
kono
parents: 68
diff changeset
2662 9 0x85 \205 (cont) 21-26
kono
parents: 68
diff changeset
2663 10 0xB5 \265 (cont) 21-26
kono
parents: 68
diff changeset
2664 11 0x37 '7' 27
kono
parents: 68
diff changeset
2665 12 0x38 '8' 28
kono
parents: 68
diff changeset
2666 13 0x39 '9' 29
kono
parents: 68
diff changeset
2667 14 0x00 30 (closing quote)
kono
parents: 68
diff changeset
2668 ----------- ---- ----- ------- ---------------. */
kono
parents: 68
diff changeset
2669
kono
parents: 68
diff changeset
2670 cpp_string dst_string;
kono
parents: 68
diff changeset
2671 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2672 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2673 &dst_string, type);
kono
parents: 68
diff changeset
2674 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2675 ASSERT_STREQ ("01234\342\205\264\342\205\265789",
kono
parents: 68
diff changeset
2676 (const char *)dst_string.text);
kono
parents: 68
diff changeset
2677 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2678
kono
parents: 68
diff changeset
2679 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2680 opening quote, but does include the closing quote.
kono
parents: 68
diff changeset
2681 '01234'. */
kono
parents: 68
diff changeset
2682 for (int i = 0; i <= 4; i++)
kono
parents: 68
diff changeset
2683 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2684 /* U+2174. */
kono
parents: 68
diff changeset
2685 for (int i = 5; i <= 7; i++)
kono
parents: 68
diff changeset
2686 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 15, 20);
kono
parents: 68
diff changeset
2687 /* U+2175. */
kono
parents: 68
diff changeset
2688 for (int i = 8; i <= 10; i++)
kono
parents: 68
diff changeset
2689 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 21, 26);
kono
parents: 68
diff changeset
2690 /* '789' and nul terminator */
kono
parents: 68
diff changeset
2691 for (int i = 11; i <= 14; i++)
kono
parents: 68
diff changeset
2692 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 16 + i, 16 + i);
kono
parents: 68
diff changeset
2693
kono
parents: 68
diff changeset
2694 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 15);
kono
parents: 68
diff changeset
2695 }
kono
parents: 68
diff changeset
2696
kono
parents: 68
diff changeset
2697 /* Lex a string literal containing UCN 8 characters.
kono
parents: 68
diff changeset
2698 Verify the substring location data after running cpp_interpret_string
kono
parents: 68
diff changeset
2699 on it. */
kono
parents: 68
diff changeset
2700
kono
parents: 68
diff changeset
2701 static void
kono
parents: 68
diff changeset
2702 test_lexer_string_locations_ucn8 (const line_table_case &case_)
kono
parents: 68
diff changeset
2703 {
kono
parents: 68
diff changeset
2704 /* Digits 0-9, expressing digits 5 and 6 as Roman numerals as UCN 8.
kono
parents: 68
diff changeset
2705 ....................000000000.111111.1111222222.2222333333333.344444
kono
parents: 68
diff changeset
2706 ....................123456789.012345.6789012345.6789012345678.901234 */
kono
parents: 68
diff changeset
2707 const char *content = " \"01234\\U00002174\\U00002175789\" /* */\n";
kono
parents: 68
diff changeset
2708 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2709
kono
parents: 68
diff changeset
2710 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2711 location information. */
kono
parents: 68
diff changeset
2712 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2713 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2714 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok,
kono
parents: 68
diff changeset
2715 "\"01234\\U00002174\\U00002175789\"");
kono
parents: 68
diff changeset
2716
kono
parents: 68
diff changeset
2717 /* Verify that cpp_interpret_string works.
kono
parents: 68
diff changeset
2718 The UTF-8 encoding of the string is identical to that from
kono
parents: 68
diff changeset
2719 the ucn4 testcase above; the only difference is the column
kono
parents: 68
diff changeset
2720 locations. */
kono
parents: 68
diff changeset
2721 cpp_string dst_string;
kono
parents: 68
diff changeset
2722 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2723 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2724 &dst_string, type);
kono
parents: 68
diff changeset
2725 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2726 ASSERT_STREQ ("01234\342\205\264\342\205\265789",
kono
parents: 68
diff changeset
2727 (const char *)dst_string.text);
kono
parents: 68
diff changeset
2728 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2729
kono
parents: 68
diff changeset
2730 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2731 opening quote, but does include the closing quote.
kono
parents: 68
diff changeset
2732 '01234'. */
kono
parents: 68
diff changeset
2733 for (int i = 0; i <= 4; i++)
kono
parents: 68
diff changeset
2734 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2735 /* U+2174. */
kono
parents: 68
diff changeset
2736 for (int i = 5; i <= 7; i++)
kono
parents: 68
diff changeset
2737 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 15, 24);
kono
parents: 68
diff changeset
2738 /* U+2175. */
kono
parents: 68
diff changeset
2739 for (int i = 8; i <= 10; i++)
kono
parents: 68
diff changeset
2740 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 25, 34);
kono
parents: 68
diff changeset
2741 /* '789' at columns 35-37 */
kono
parents: 68
diff changeset
2742 for (int i = 11; i <= 13; i++)
kono
parents: 68
diff changeset
2743 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 24 + i, 24 + i);
kono
parents: 68
diff changeset
2744 /* Closing quote/nul-terminator at column 38. */
kono
parents: 68
diff changeset
2745 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 14, 1, 38, 38);
kono
parents: 68
diff changeset
2746
kono
parents: 68
diff changeset
2747 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 15);
kono
parents: 68
diff changeset
2748 }
kono
parents: 68
diff changeset
2749
kono
parents: 68
diff changeset
2750 /* Fetch a big-endian 32-bit value and convert to host endianness. */
kono
parents: 68
diff changeset
2751
kono
parents: 68
diff changeset
2752 static uint32_t
kono
parents: 68
diff changeset
2753 uint32_from_big_endian (const uint32_t *ptr_be_value)
kono
parents: 68
diff changeset
2754 {
kono
parents: 68
diff changeset
2755 const unsigned char *buf = (const unsigned char *)ptr_be_value;
kono
parents: 68
diff changeset
2756 return (((uint32_t) buf[0] << 24)
kono
parents: 68
diff changeset
2757 | ((uint32_t) buf[1] << 16)
kono
parents: 68
diff changeset
2758 | ((uint32_t) buf[2] << 8)
kono
parents: 68
diff changeset
2759 | (uint32_t) buf[3]);
kono
parents: 68
diff changeset
2760 }
kono
parents: 68
diff changeset
2761
kono
parents: 68
diff changeset
2762 /* Lex a wide string literal and verify that attempts to read substring
kono
parents: 68
diff changeset
2763 location data from it fail gracefully. */
kono
parents: 68
diff changeset
2764
kono
parents: 68
diff changeset
2765 static void
kono
parents: 68
diff changeset
2766 test_lexer_string_locations_wide_string (const line_table_case &case_)
kono
parents: 68
diff changeset
2767 {
kono
parents: 68
diff changeset
2768 /* Digits 0-9.
kono
parents: 68
diff changeset
2769 ....................000000000.11111111112.22222222233333
kono
parents: 68
diff changeset
2770 ....................123456789.01234567890.12345678901234 */
kono
parents: 68
diff changeset
2771 const char *content = " L\"0123456789\" /* non-str */\n";
kono
parents: 68
diff changeset
2772 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2773
kono
parents: 68
diff changeset
2774 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2775 location information. */
kono
parents: 68
diff changeset
2776 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2777 ASSERT_EQ (tok->type, CPP_WSTRING);
kono
parents: 68
diff changeset
2778 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "L\"0123456789\"");
kono
parents: 68
diff changeset
2779
kono
parents: 68
diff changeset
2780 /* Verify that cpp_interpret_string works, using CPP_WSTRING. */
kono
parents: 68
diff changeset
2781 cpp_string dst_string;
kono
parents: 68
diff changeset
2782 const enum cpp_ttype type = CPP_WSTRING;
kono
parents: 68
diff changeset
2783 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2784 &dst_string, type);
kono
parents: 68
diff changeset
2785 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2786 /* The cpp_reader defaults to big-endian with
kono
parents: 68
diff changeset
2787 CHAR_BIT * sizeof (int) for the wchar_precision, so dst_string should
kono
parents: 68
diff changeset
2788 now be encoded as UTF-32BE. */
kono
parents: 68
diff changeset
2789 const uint32_t *be32_chars = (const uint32_t *)dst_string.text;
kono
parents: 68
diff changeset
2790 ASSERT_EQ ('0', uint32_from_big_endian (&be32_chars[0]));
kono
parents: 68
diff changeset
2791 ASSERT_EQ ('5', uint32_from_big_endian (&be32_chars[5]));
kono
parents: 68
diff changeset
2792 ASSERT_EQ ('9', uint32_from_big_endian (&be32_chars[9]));
kono
parents: 68
diff changeset
2793 ASSERT_EQ (0, uint32_from_big_endian (&be32_chars[10]));
kono
parents: 68
diff changeset
2794 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2795
kono
parents: 68
diff changeset
2796 /* We don't yet support generating substring location information
kono
parents: 68
diff changeset
2797 for L"" strings. */
kono
parents: 68
diff changeset
2798 ASSERT_HAS_NO_SUBSTRING_RANGES
kono
parents: 68
diff changeset
2799 (test, tok->src_loc, type,
kono
parents: 68
diff changeset
2800 "execution character set != source character set");
kono
parents: 68
diff changeset
2801 }
kono
parents: 68
diff changeset
2802
kono
parents: 68
diff changeset
2803 /* Fetch a big-endian 16-bit value and convert to host endianness. */
kono
parents: 68
diff changeset
2804
kono
parents: 68
diff changeset
2805 static uint16_t
kono
parents: 68
diff changeset
2806 uint16_from_big_endian (const uint16_t *ptr_be_value)
kono
parents: 68
diff changeset
2807 {
kono
parents: 68
diff changeset
2808 const unsigned char *buf = (const unsigned char *)ptr_be_value;
kono
parents: 68
diff changeset
2809 return ((uint16_t) buf[0] << 8) | (uint16_t) buf[1];
kono
parents: 68
diff changeset
2810 }
kono
parents: 68
diff changeset
2811
kono
parents: 68
diff changeset
2812 /* Lex a u"" string literal and verify that attempts to read substring
kono
parents: 68
diff changeset
2813 location data from it fail gracefully. */
kono
parents: 68
diff changeset
2814
kono
parents: 68
diff changeset
2815 static void
kono
parents: 68
diff changeset
2816 test_lexer_string_locations_string16 (const line_table_case &case_)
kono
parents: 68
diff changeset
2817 {
kono
parents: 68
diff changeset
2818 /* Digits 0-9.
kono
parents: 68
diff changeset
2819 ....................000000000.11111111112.22222222233333
kono
parents: 68
diff changeset
2820 ....................123456789.01234567890.12345678901234 */
kono
parents: 68
diff changeset
2821 const char *content = " u\"0123456789\" /* non-str */\n";
kono
parents: 68
diff changeset
2822 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2823
kono
parents: 68
diff changeset
2824 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2825 location information. */
kono
parents: 68
diff changeset
2826 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2827 ASSERT_EQ (tok->type, CPP_STRING16);
kono
parents: 68
diff changeset
2828 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u\"0123456789\"");
kono
parents: 68
diff changeset
2829
kono
parents: 68
diff changeset
2830 /* Verify that cpp_interpret_string works, using CPP_STRING16. */
kono
parents: 68
diff changeset
2831 cpp_string dst_string;
kono
parents: 68
diff changeset
2832 const enum cpp_ttype type = CPP_STRING16;
kono
parents: 68
diff changeset
2833 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2834 &dst_string, type);
kono
parents: 68
diff changeset
2835 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2836
kono
parents: 68
diff changeset
2837 /* The cpp_reader defaults to big-endian, so dst_string should
kono
parents: 68
diff changeset
2838 now be encoded as UTF-16BE. */
kono
parents: 68
diff changeset
2839 const uint16_t *be16_chars = (const uint16_t *)dst_string.text;
kono
parents: 68
diff changeset
2840 ASSERT_EQ ('0', uint16_from_big_endian (&be16_chars[0]));
kono
parents: 68
diff changeset
2841 ASSERT_EQ ('5', uint16_from_big_endian (&be16_chars[5]));
kono
parents: 68
diff changeset
2842 ASSERT_EQ ('9', uint16_from_big_endian (&be16_chars[9]));
kono
parents: 68
diff changeset
2843 ASSERT_EQ (0, uint16_from_big_endian (&be16_chars[10]));
kono
parents: 68
diff changeset
2844 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2845
kono
parents: 68
diff changeset
2846 /* We don't yet support generating substring location information
kono
parents: 68
diff changeset
2847 for L"" strings. */
kono
parents: 68
diff changeset
2848 ASSERT_HAS_NO_SUBSTRING_RANGES
kono
parents: 68
diff changeset
2849 (test, tok->src_loc, type,
kono
parents: 68
diff changeset
2850 "execution character set != source character set");
kono
parents: 68
diff changeset
2851 }
kono
parents: 68
diff changeset
2852
kono
parents: 68
diff changeset
2853 /* Lex a U"" string literal and verify that attempts to read substring
kono
parents: 68
diff changeset
2854 location data from it fail gracefully. */
kono
parents: 68
diff changeset
2855
kono
parents: 68
diff changeset
2856 static void
kono
parents: 68
diff changeset
2857 test_lexer_string_locations_string32 (const line_table_case &case_)
kono
parents: 68
diff changeset
2858 {
kono
parents: 68
diff changeset
2859 /* Digits 0-9.
kono
parents: 68
diff changeset
2860 ....................000000000.11111111112.22222222233333
kono
parents: 68
diff changeset
2861 ....................123456789.01234567890.12345678901234 */
kono
parents: 68
diff changeset
2862 const char *content = " U\"0123456789\" /* non-str */\n";
kono
parents: 68
diff changeset
2863 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2864
kono
parents: 68
diff changeset
2865 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2866 location information. */
kono
parents: 68
diff changeset
2867 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2868 ASSERT_EQ (tok->type, CPP_STRING32);
kono
parents: 68
diff changeset
2869 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "U\"0123456789\"");
kono
parents: 68
diff changeset
2870
kono
parents: 68
diff changeset
2871 /* Verify that cpp_interpret_string works, using CPP_STRING32. */
kono
parents: 68
diff changeset
2872 cpp_string dst_string;
kono
parents: 68
diff changeset
2873 const enum cpp_ttype type = CPP_STRING32;
kono
parents: 68
diff changeset
2874 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2875 &dst_string, type);
kono
parents: 68
diff changeset
2876 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2877
kono
parents: 68
diff changeset
2878 /* The cpp_reader defaults to big-endian, so dst_string should
kono
parents: 68
diff changeset
2879 now be encoded as UTF-32BE. */
kono
parents: 68
diff changeset
2880 const uint32_t *be32_chars = (const uint32_t *)dst_string.text;
kono
parents: 68
diff changeset
2881 ASSERT_EQ ('0', uint32_from_big_endian (&be32_chars[0]));
kono
parents: 68
diff changeset
2882 ASSERT_EQ ('5', uint32_from_big_endian (&be32_chars[5]));
kono
parents: 68
diff changeset
2883 ASSERT_EQ ('9', uint32_from_big_endian (&be32_chars[9]));
kono
parents: 68
diff changeset
2884 ASSERT_EQ (0, uint32_from_big_endian (&be32_chars[10]));
kono
parents: 68
diff changeset
2885 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2886
kono
parents: 68
diff changeset
2887 /* We don't yet support generating substring location information
kono
parents: 68
diff changeset
2888 for L"" strings. */
kono
parents: 68
diff changeset
2889 ASSERT_HAS_NO_SUBSTRING_RANGES
kono
parents: 68
diff changeset
2890 (test, tok->src_loc, type,
kono
parents: 68
diff changeset
2891 "execution character set != source character set");
68
561a7518be6b update gcc-4.6
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2892 }
111
kono
parents: 68
diff changeset
2893
kono
parents: 68
diff changeset
2894 /* Lex a u8-string literal.
kono
parents: 68
diff changeset
2895 Verify the substring location data after running cpp_interpret_string
kono
parents: 68
diff changeset
2896 on it. */
kono
parents: 68
diff changeset
2897
kono
parents: 68
diff changeset
2898 static void
kono
parents: 68
diff changeset
2899 test_lexer_string_locations_u8 (const line_table_case &case_)
kono
parents: 68
diff changeset
2900 {
kono
parents: 68
diff changeset
2901 /* Digits 0-9.
kono
parents: 68
diff changeset
2902 ....................000000000.11111111112.22222222233333
kono
parents: 68
diff changeset
2903 ....................123456789.01234567890.12345678901234 */
kono
parents: 68
diff changeset
2904 const char *content = " u8\"0123456789\" /* non-str */\n";
kono
parents: 68
diff changeset
2905 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2906
kono
parents: 68
diff changeset
2907 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2908 location information. */
kono
parents: 68
diff changeset
2909 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2910 ASSERT_EQ (tok->type, CPP_UTF8STRING);
kono
parents: 68
diff changeset
2911 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u8\"0123456789\"");
kono
parents: 68
diff changeset
2912
kono
parents: 68
diff changeset
2913 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2914 cpp_string dst_string;
kono
parents: 68
diff changeset
2915 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2916 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2917 &dst_string, type);
kono
parents: 68
diff changeset
2918 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2919 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
2920 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2921
kono
parents: 68
diff changeset
2922 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
2923 opening quote, but does include the closing quote. */
kono
parents: 68
diff changeset
2924 for (int i = 0; i <= 10; i++)
kono
parents: 68
diff changeset
2925 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
2926 }
kono
parents: 68
diff changeset
2927
kono
parents: 68
diff changeset
2928 /* Lex a string literal containing UTF-8 source characters.
kono
parents: 68
diff changeset
2929 Verify the substring location data after running cpp_interpret_string
kono
parents: 68
diff changeset
2930 on it. */
kono
parents: 68
diff changeset
2931
kono
parents: 68
diff changeset
2932 static void
kono
parents: 68
diff changeset
2933 test_lexer_string_locations_utf8_source (const line_table_case &case_)
kono
parents: 68
diff changeset
2934 {
kono
parents: 68
diff changeset
2935 /* This string literal is written out to the source file as UTF-8,
kono
parents: 68
diff changeset
2936 and is of the form "before mojibake after", where "mojibake"
kono
parents: 68
diff changeset
2937 is written as the following four unicode code points:
kono
parents: 68
diff changeset
2938 U+6587 CJK UNIFIED IDEOGRAPH-6587
kono
parents: 68
diff changeset
2939 U+5B57 CJK UNIFIED IDEOGRAPH-5B57
kono
parents: 68
diff changeset
2940 U+5316 CJK UNIFIED IDEOGRAPH-5316
kono
parents: 68
diff changeset
2941 U+3051 HIRAGANA LETTER KE.
kono
parents: 68
diff changeset
2942 Each of these is 3 bytes wide when encoded in UTF-8, whereas the
kono
parents: 68
diff changeset
2943 "before" and "after" are 1 byte per unicode character.
kono
parents: 68
diff changeset
2944
kono
parents: 68
diff changeset
2945 The numbering shown are "columns", which are *byte* numbers within
kono
parents: 68
diff changeset
2946 the line, rather than unicode character numbers.
kono
parents: 68
diff changeset
2947
kono
parents: 68
diff changeset
2948 .................... 000000000.1111111.
kono
parents: 68
diff changeset
2949 .................... 123456789.0123456. */
kono
parents: 68
diff changeset
2950 const char *content = (" \"before "
kono
parents: 68
diff changeset
2951 /* U+6587 CJK UNIFIED IDEOGRAPH-6587
kono
parents: 68
diff changeset
2952 UTF-8: 0xE6 0x96 0x87
kono
parents: 68
diff changeset
2953 C octal escaped UTF-8: \346\226\207
kono
parents: 68
diff changeset
2954 "column" numbers: 17-19. */
kono
parents: 68
diff changeset
2955 "\346\226\207"
kono
parents: 68
diff changeset
2956
kono
parents: 68
diff changeset
2957 /* U+5B57 CJK UNIFIED IDEOGRAPH-5B57
kono
parents: 68
diff changeset
2958 UTF-8: 0xE5 0xAD 0x97
kono
parents: 68
diff changeset
2959 C octal escaped UTF-8: \345\255\227
kono
parents: 68
diff changeset
2960 "column" numbers: 20-22. */
kono
parents: 68
diff changeset
2961 "\345\255\227"
kono
parents: 68
diff changeset
2962
kono
parents: 68
diff changeset
2963 /* U+5316 CJK UNIFIED IDEOGRAPH-5316
kono
parents: 68
diff changeset
2964 UTF-8: 0xE5 0x8C 0x96
kono
parents: 68
diff changeset
2965 C octal escaped UTF-8: \345\214\226
kono
parents: 68
diff changeset
2966 "column" numbers: 23-25. */
kono
parents: 68
diff changeset
2967 "\345\214\226"
kono
parents: 68
diff changeset
2968
kono
parents: 68
diff changeset
2969 /* U+3051 HIRAGANA LETTER KE
kono
parents: 68
diff changeset
2970 UTF-8: 0xE3 0x81 0x91
kono
parents: 68
diff changeset
2971 C octal escaped UTF-8: \343\201\221
kono
parents: 68
diff changeset
2972 "column" numbers: 26-28. */
kono
parents: 68
diff changeset
2973 "\343\201\221"
kono
parents: 68
diff changeset
2974
kono
parents: 68
diff changeset
2975 /* column numbers 29 onwards
kono
parents: 68
diff changeset
2976 2333333.33334444444444
kono
parents: 68
diff changeset
2977 9012345.67890123456789. */
kono
parents: 68
diff changeset
2978 " after\" /* non-str */\n");
kono
parents: 68
diff changeset
2979 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
2980
kono
parents: 68
diff changeset
2981 /* Verify that we get the expected token back, with the correct
kono
parents: 68
diff changeset
2982 location information. */
kono
parents: 68
diff changeset
2983 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
2984 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
2985 ASSERT_TOKEN_AS_TEXT_EQ
kono
parents: 68
diff changeset
2986 (test.m_parser, tok,
kono
parents: 68
diff changeset
2987 "\"before \346\226\207\345\255\227\345\214\226\343\201\221 after\"");
kono
parents: 68
diff changeset
2988
kono
parents: 68
diff changeset
2989 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
2990 cpp_string dst_string;
kono
parents: 68
diff changeset
2991 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
2992 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
2993 &dst_string, type);
kono
parents: 68
diff changeset
2994 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
2995 ASSERT_STREQ
kono
parents: 68
diff changeset
2996 ("before \346\226\207\345\255\227\345\214\226\343\201\221 after",
kono
parents: 68
diff changeset
2997 (const char *)dst_string.text);
kono
parents: 68
diff changeset
2998 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
2999
kono
parents: 68
diff changeset
3000 /* Verify ranges of individual characters. This no longer includes the
kono
parents: 68
diff changeset
3001 opening quote, but does include the closing quote.
kono
parents: 68
diff changeset
3002 Assuming that both source and execution encodings are UTF-8, we have
kono
parents: 68
diff changeset
3003 a run of 25 octets in each, plus the NUL terminator. */
kono
parents: 68
diff changeset
3004 for (int i = 0; i < 25; i++)
kono
parents: 68
diff changeset
3005 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
3006 /* NUL-terminator should use the closing quote at column 35. */
kono
parents: 68
diff changeset
3007 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, type, 25, 1, 35, 35);
kono
parents: 68
diff changeset
3008
kono
parents: 68
diff changeset
3009 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, type, 26);
kono
parents: 68
diff changeset
3010 }
kono
parents: 68
diff changeset
3011
kono
parents: 68
diff changeset
3012 /* Test of string literal concatenation. */
kono
parents: 68
diff changeset
3013
kono
parents: 68
diff changeset
3014 static void
kono
parents: 68
diff changeset
3015 test_lexer_string_locations_concatenation_1 (const line_table_case &case_)
kono
parents: 68
diff changeset
3016 {
kono
parents: 68
diff changeset
3017 /* Digits 0-9.
kono
parents: 68
diff changeset
3018 .....................000000000.111111.11112222222222
kono
parents: 68
diff changeset
3019 .....................123456789.012345.67890123456789. */
kono
parents: 68
diff changeset
3020 const char *content = (" \"01234\" /* non-str */\n"
kono
parents: 68
diff changeset
3021 " \"56789\" /* non-str */\n");
kono
parents: 68
diff changeset
3022 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3023
kono
parents: 68
diff changeset
3024 location_t input_locs[2];
kono
parents: 68
diff changeset
3025
kono
parents: 68
diff changeset
3026 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
3027 auto_vec <cpp_string> input_strings;
kono
parents: 68
diff changeset
3028 const cpp_token *tok_a = test.get_token ();
kono
parents: 68
diff changeset
3029 ASSERT_EQ (tok_a->type, CPP_STRING);
kono
parents: 68
diff changeset
3030 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok_a, "\"01234\"");
kono
parents: 68
diff changeset
3031 input_strings.safe_push (tok_a->val.str);
kono
parents: 68
diff changeset
3032 input_locs[0] = tok_a->src_loc;
kono
parents: 68
diff changeset
3033
kono
parents: 68
diff changeset
3034 const cpp_token *tok_b = test.get_token ();
kono
parents: 68
diff changeset
3035 ASSERT_EQ (tok_b->type, CPP_STRING);
kono
parents: 68
diff changeset
3036 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok_b, "\"56789\"");
kono
parents: 68
diff changeset
3037 input_strings.safe_push (tok_b->val.str);
kono
parents: 68
diff changeset
3038 input_locs[1] = tok_b->src_loc;
kono
parents: 68
diff changeset
3039
kono
parents: 68
diff changeset
3040 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
3041 cpp_string dst_string;
kono
parents: 68
diff changeset
3042 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
3043 bool result = cpp_interpret_string (test.m_parser,
kono
parents: 68
diff changeset
3044 input_strings.address (), 2,
kono
parents: 68
diff changeset
3045 &dst_string, type);
kono
parents: 68
diff changeset
3046 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
3047 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
3048 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
3049
kono
parents: 68
diff changeset
3050 /* Simulate c-lex.c's lex_string in order to record concatenation. */
kono
parents: 68
diff changeset
3051 test.m_concats.record_string_concatenation (2, input_locs);
kono
parents: 68
diff changeset
3052
kono
parents: 68
diff changeset
3053 location_t initial_loc = input_locs[0];
kono
parents: 68
diff changeset
3054
kono
parents: 68
diff changeset
3055 /* "01234" on line 1. */
kono
parents: 68
diff changeset
3056 for (int i = 0; i <= 4; i++)
kono
parents: 68
diff changeset
3057 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
3058 /* "56789" in line 2, plus its closing quote for the nul terminator. */
kono
parents: 68
diff changeset
3059 for (int i = 5; i <= 10; i++)
kono
parents: 68
diff changeset
3060 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 2, 5 + i, 5 + i);
kono
parents: 68
diff changeset
3061
kono
parents: 68
diff changeset
3062 ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
kono
parents: 68
diff changeset
3063 }
kono
parents: 68
diff changeset
3064
kono
parents: 68
diff changeset
3065 /* Another test of string literal concatenation. */
kono
parents: 68
diff changeset
3066
kono
parents: 68
diff changeset
3067 static void
kono
parents: 68
diff changeset
3068 test_lexer_string_locations_concatenation_2 (const line_table_case &case_)
kono
parents: 68
diff changeset
3069 {
kono
parents: 68
diff changeset
3070 /* Digits 0-9.
kono
parents: 68
diff changeset
3071 .....................000000000.111.11111112222222
kono
parents: 68
diff changeset
3072 .....................123456789.012.34567890123456. */
kono
parents: 68
diff changeset
3073 const char *content = (" \"01\" /* non-str */\n"
kono
parents: 68
diff changeset
3074 " \"23\" /* non-str */\n"
kono
parents: 68
diff changeset
3075 " \"45\" /* non-str */\n"
kono
parents: 68
diff changeset
3076 " \"67\" /* non-str */\n"
kono
parents: 68
diff changeset
3077 " \"89\" /* non-str */\n");
kono
parents: 68
diff changeset
3078 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3079
kono
parents: 68
diff changeset
3080 auto_vec <cpp_string> input_strings;
kono
parents: 68
diff changeset
3081 location_t input_locs[5];
kono
parents: 68
diff changeset
3082
kono
parents: 68
diff changeset
3083 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
3084 for (int i = 0; i < 5; i++)
kono
parents: 68
diff changeset
3085 {
kono
parents: 68
diff changeset
3086 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3087 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3088 input_strings.safe_push (tok->val.str);
kono
parents: 68
diff changeset
3089 input_locs[i] = tok->src_loc;
kono
parents: 68
diff changeset
3090 }
kono
parents: 68
diff changeset
3091
kono
parents: 68
diff changeset
3092 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
3093 cpp_string dst_string;
kono
parents: 68
diff changeset
3094 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
3095 bool result = cpp_interpret_string (test.m_parser,
kono
parents: 68
diff changeset
3096 input_strings.address (), 5,
kono
parents: 68
diff changeset
3097 &dst_string, type);
kono
parents: 68
diff changeset
3098 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
3099 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
3100 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
3101
kono
parents: 68
diff changeset
3102 /* Simulate c-lex.c's lex_string in order to record concatenation. */
kono
parents: 68
diff changeset
3103 test.m_concats.record_string_concatenation (5, input_locs);
kono
parents: 68
diff changeset
3104
kono
parents: 68
diff changeset
3105 location_t initial_loc = input_locs[0];
kono
parents: 68
diff changeset
3106
kono
parents: 68
diff changeset
3107 /* Within ASSERT_CHAR_AT_RANGE (actually assert_char_at_range), we can
kono
parents: 68
diff changeset
3108 detect if the initial loc is after LINE_MAP_MAX_LOCATION_WITH_COLS
kono
parents: 68
diff changeset
3109 and expect get_source_range_for_substring to fail.
kono
parents: 68
diff changeset
3110 However, for a string concatenation test, we can have a case
kono
parents: 68
diff changeset
3111 where the initial string is fully before LINE_MAP_MAX_LOCATION_WITH_COLS,
kono
parents: 68
diff changeset
3112 but subsequent strings can be after it.
kono
parents: 68
diff changeset
3113 Attempting to detect this within assert_char_at_range
kono
parents: 68
diff changeset
3114 would overcomplicate the logic for the common test cases, so
kono
parents: 68
diff changeset
3115 we detect it here. */
kono
parents: 68
diff changeset
3116 if (should_have_column_data_p (input_locs[0])
kono
parents: 68
diff changeset
3117 && !should_have_column_data_p (input_locs[4]))
kono
parents: 68
diff changeset
3118 {
kono
parents: 68
diff changeset
3119 /* Verify that get_source_range_for_substring gracefully rejects
kono
parents: 68
diff changeset
3120 this case. */
kono
parents: 68
diff changeset
3121 source_range actual_range;
kono
parents: 68
diff changeset
3122 const char *err
kono
parents: 68
diff changeset
3123 = get_source_range_for_char (test.m_parser, &test.m_concats,
kono
parents: 68
diff changeset
3124 initial_loc, type, 0, &actual_range);
kono
parents: 68
diff changeset
3125 ASSERT_STREQ ("range starts after LINE_MAP_MAX_LOCATION_WITH_COLS", err);
kono
parents: 68
diff changeset
3126 return;
kono
parents: 68
diff changeset
3127 }
kono
parents: 68
diff changeset
3128
kono
parents: 68
diff changeset
3129 for (int i = 0; i < 5; i++)
kono
parents: 68
diff changeset
3130 for (int j = 0; j < 2; j++)
kono
parents: 68
diff changeset
3131 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, (i * 2) + j,
kono
parents: 68
diff changeset
3132 i + 1, 10 + j, 10 + j);
kono
parents: 68
diff changeset
3133
kono
parents: 68
diff changeset
3134 /* NUL-terminator should use the final closing quote at line 5 column 12. */
kono
parents: 68
diff changeset
3135 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 10, 5, 12, 12);
kono
parents: 68
diff changeset
3136
kono
parents: 68
diff changeset
3137 ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
kono
parents: 68
diff changeset
3138 }
kono
parents: 68
diff changeset
3139
kono
parents: 68
diff changeset
3140 /* Another test of string literal concatenation, this time combined with
kono
parents: 68
diff changeset
3141 various kinds of escaped characters. */
kono
parents: 68
diff changeset
3142
kono
parents: 68
diff changeset
3143 static void
kono
parents: 68
diff changeset
3144 test_lexer_string_locations_concatenation_3 (const line_table_case &case_)
kono
parents: 68
diff changeset
3145 {
kono
parents: 68
diff changeset
3146 /* Digits 0-9, expressing digit 5 in ASCII as hex "\x35"
kono
parents: 68
diff changeset
3147 digit 6 in ASCII as octal "\066", concatenating multiple strings. */
kono
parents: 68
diff changeset
3148 const char *content
kono
parents: 68
diff changeset
3149 /* .000000000.111111.111.1.2222.222.2.2233.333.3333.34444444444555
kono
parents: 68
diff changeset
3150 .123456789.012345.678.9.0123.456.7.8901.234.5678.90123456789012. */
kono
parents: 68
diff changeset
3151 = (" \"01234\" \"\\x35\" \"\\066\" \"789\" /* non-str */\n");
kono
parents: 68
diff changeset
3152 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3153
kono
parents: 68
diff changeset
3154 auto_vec <cpp_string> input_strings;
kono
parents: 68
diff changeset
3155 location_t input_locs[4];
kono
parents: 68
diff changeset
3156
kono
parents: 68
diff changeset
3157 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
3158 for (int i = 0; i < 4; i++)
kono
parents: 68
diff changeset
3159 {
kono
parents: 68
diff changeset
3160 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3161 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3162 input_strings.safe_push (tok->val.str);
kono
parents: 68
diff changeset
3163 input_locs[i] = tok->src_loc;
kono
parents: 68
diff changeset
3164 }
kono
parents: 68
diff changeset
3165
kono
parents: 68
diff changeset
3166 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
3167 cpp_string dst_string;
kono
parents: 68
diff changeset
3168 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
3169 bool result = cpp_interpret_string (test.m_parser,
kono
parents: 68
diff changeset
3170 input_strings.address (), 4,
kono
parents: 68
diff changeset
3171 &dst_string, type);
kono
parents: 68
diff changeset
3172 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
3173 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
3174 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
3175
kono
parents: 68
diff changeset
3176 /* Simulate c-lex.c's lex_string in order to record concatenation. */
kono
parents: 68
diff changeset
3177 test.m_concats.record_string_concatenation (4, input_locs);
kono
parents: 68
diff changeset
3178
kono
parents: 68
diff changeset
3179 location_t initial_loc = input_locs[0];
kono
parents: 68
diff changeset
3180
kono
parents: 68
diff changeset
3181 for (int i = 0; i <= 4; i++)
kono
parents: 68
diff changeset
3182 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 10 + i, 10 + i);
kono
parents: 68
diff changeset
3183 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 5, 1, 19, 22);
kono
parents: 68
diff changeset
3184 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 6, 1, 27, 30);
kono
parents: 68
diff changeset
3185 for (int i = 7; i <= 9; i++)
kono
parents: 68
diff changeset
3186 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, i, 1, 28 + i, 28 + i);
kono
parents: 68
diff changeset
3187
kono
parents: 68
diff changeset
3188 /* NUL-terminator should use the location of the final closing quote. */
kono
parents: 68
diff changeset
3189 ASSERT_CHAR_AT_RANGE (test, initial_loc, type, 10, 1, 38, 38);
kono
parents: 68
diff changeset
3190
kono
parents: 68
diff changeset
3191 ASSERT_NUM_SUBSTRING_RANGES (test, initial_loc, type, 11);
kono
parents: 68
diff changeset
3192 }
kono
parents: 68
diff changeset
3193
kono
parents: 68
diff changeset
3194 /* Test of string literal in a macro. */
kono
parents: 68
diff changeset
3195
kono
parents: 68
diff changeset
3196 static void
kono
parents: 68
diff changeset
3197 test_lexer_string_locations_macro (const line_table_case &case_)
kono
parents: 68
diff changeset
3198 {
kono
parents: 68
diff changeset
3199 /* Digits 0-9.
kono
parents: 68
diff changeset
3200 .....................0000000001111111111.22222222223.
kono
parents: 68
diff changeset
3201 .....................1234567890123456789.01234567890. */
kono
parents: 68
diff changeset
3202 const char *content = ("#define MACRO \"0123456789\" /* non-str */\n"
kono
parents: 68
diff changeset
3203 " MACRO");
kono
parents: 68
diff changeset
3204 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3205
kono
parents: 68
diff changeset
3206 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
3207 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3208 ASSERT_EQ (tok->type, CPP_PADDING);
kono
parents: 68
diff changeset
3209
kono
parents: 68
diff changeset
3210 tok = test.get_token ();
kono
parents: 68
diff changeset
3211 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3212 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"0123456789\"");
kono
parents: 68
diff changeset
3213
kono
parents: 68
diff changeset
3214 /* Verify ranges of individual characters. We ought to
kono
parents: 68
diff changeset
3215 see columns within the macro definition. */
kono
parents: 68
diff changeset
3216 for (int i = 0; i <= 10; i++)
kono
parents: 68
diff changeset
3217 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
3218 i, 1, 20 + i, 20 + i);
kono
parents: 68
diff changeset
3219
kono
parents: 68
diff changeset
3220 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 11);
kono
parents: 68
diff changeset
3221
kono
parents: 68
diff changeset
3222 tok = test.get_token ();
kono
parents: 68
diff changeset
3223 ASSERT_EQ (tok->type, CPP_PADDING);
kono
parents: 68
diff changeset
3224 }
kono
parents: 68
diff changeset
3225
kono
parents: 68
diff changeset
3226 /* Test of stringification of a macro argument. */
kono
parents: 68
diff changeset
3227
kono
parents: 68
diff changeset
3228 static void
kono
parents: 68
diff changeset
3229 test_lexer_string_locations_stringified_macro_argument
kono
parents: 68
diff changeset
3230 (const line_table_case &case_)
kono
parents: 68
diff changeset
3231 {
kono
parents: 68
diff changeset
3232 /* .....................000000000111111111122222222223.
kono
parents: 68
diff changeset
3233 .....................123456789012345678901234567890. */
kono
parents: 68
diff changeset
3234 const char *content = ("#define MACRO(X) #X /* non-str */\n"
kono
parents: 68
diff changeset
3235 "MACRO(foo)\n");
kono
parents: 68
diff changeset
3236 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3237
kono
parents: 68
diff changeset
3238 /* Verify that we get the expected token back. */
kono
parents: 68
diff changeset
3239 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3240 ASSERT_EQ (tok->type, CPP_PADDING);
kono
parents: 68
diff changeset
3241
kono
parents: 68
diff changeset
3242 tok = test.get_token ();
kono
parents: 68
diff changeset
3243 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3244 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "\"foo\"");
kono
parents: 68
diff changeset
3245
kono
parents: 68
diff changeset
3246 /* We don't support getting the location of a stringified macro
kono
parents: 68
diff changeset
3247 argument. Verify that it fails gracefully. */
kono
parents: 68
diff changeset
3248 ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
3249 "cpp_interpret_string_1 failed");
kono
parents: 68
diff changeset
3250
kono
parents: 68
diff changeset
3251 tok = test.get_token ();
kono
parents: 68
diff changeset
3252 ASSERT_EQ (tok->type, CPP_PADDING);
kono
parents: 68
diff changeset
3253
kono
parents: 68
diff changeset
3254 tok = test.get_token ();
kono
parents: 68
diff changeset
3255 ASSERT_EQ (tok->type, CPP_PADDING);
kono
parents: 68
diff changeset
3256 }
kono
parents: 68
diff changeset
3257
kono
parents: 68
diff changeset
3258 /* Ensure that we are fail gracefully if something attempts to pass
kono
parents: 68
diff changeset
3259 in a location that isn't a string literal token. Seen on this code:
kono
parents: 68
diff changeset
3260
kono
parents: 68
diff changeset
3261 const char a[] = " %d ";
kono
parents: 68
diff changeset
3262 __builtin_printf (a, 0.5);
kono
parents: 68
diff changeset
3263 ^
kono
parents: 68
diff changeset
3264
kono
parents: 68
diff changeset
3265 when c-format.c erroneously used the indicated one-character
kono
parents: 68
diff changeset
3266 location as the format string location, leading to a read past the
kono
parents: 68
diff changeset
3267 end of a string buffer in cpp_interpret_string_1. */
kono
parents: 68
diff changeset
3268
kono
parents: 68
diff changeset
3269 static void
kono
parents: 68
diff changeset
3270 test_lexer_string_locations_non_string (const line_table_case &case_)
kono
parents: 68
diff changeset
3271 {
kono
parents: 68
diff changeset
3272 /* .....................000000000111111111122222222223.
kono
parents: 68
diff changeset
3273 .....................123456789012345678901234567890. */
kono
parents: 68
diff changeset
3274 const char *content = (" a\n");
kono
parents: 68
diff changeset
3275 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3276
kono
parents: 68
diff changeset
3277 /* Verify that we get the expected token back. */
kono
parents: 68
diff changeset
3278 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3279 ASSERT_EQ (tok->type, CPP_NAME);
kono
parents: 68
diff changeset
3280 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "a");
kono
parents: 68
diff changeset
3281
kono
parents: 68
diff changeset
3282 /* At this point, libcpp is attempting to interpret the name as a
kono
parents: 68
diff changeset
3283 string literal, despite it not starting with a quote. We don't detect
kono
parents: 68
diff changeset
3284 that, but we should at least fail gracefully. */
kono
parents: 68
diff changeset
3285 ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
3286 "cpp_interpret_string_1 failed");
kono
parents: 68
diff changeset
3287 }
kono
parents: 68
diff changeset
3288
kono
parents: 68
diff changeset
3289 /* Ensure that we can read substring information for a token which
kono
parents: 68
diff changeset
3290 starts in one linemap and ends in another . Adapted from
kono
parents: 68
diff changeset
3291 gcc.dg/cpp/pr69985.c. */
kono
parents: 68
diff changeset
3292
kono
parents: 68
diff changeset
3293 static void
kono
parents: 68
diff changeset
3294 test_lexer_string_locations_long_line (const line_table_case &case_)
kono
parents: 68
diff changeset
3295 {
kono
parents: 68
diff changeset
3296 /* .....................000000.000111111111
kono
parents: 68
diff changeset
3297 .....................123456.789012346789. */
kono
parents: 68
diff changeset
3298 const char *content = ("/* A very long line, so that we start a new line map. */\n"
kono
parents: 68
diff changeset
3299 " \"0123456789012345678901234567890123456789"
kono
parents: 68
diff changeset
3300 "0123456789012345678901234567890123456789"
kono
parents: 68
diff changeset
3301 "0123456789012345678901234567890123456789"
kono
parents: 68
diff changeset
3302 "0123456789\"\n");
kono
parents: 68
diff changeset
3303
kono
parents: 68
diff changeset
3304 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3305
kono
parents: 68
diff changeset
3306 /* Verify that we get the expected token back. */
kono
parents: 68
diff changeset
3307 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3308 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3309
kono
parents: 68
diff changeset
3310 if (!should_have_column_data_p (line_table->highest_location))
kono
parents: 68
diff changeset
3311 return;
kono
parents: 68
diff changeset
3312
kono
parents: 68
diff changeset
3313 /* Verify ranges of individual characters. */
kono
parents: 68
diff changeset
3314 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 131);
kono
parents: 68
diff changeset
3315 for (int i = 0; i < 131; i++)
kono
parents: 68
diff changeset
3316 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
3317 i, 2, 7 + i, 7 + i);
kono
parents: 68
diff changeset
3318 }
kono
parents: 68
diff changeset
3319
kono
parents: 68
diff changeset
3320 /* Test of locations within a raw string that doesn't contain a newline. */
kono
parents: 68
diff changeset
3321
kono
parents: 68
diff changeset
3322 static void
kono
parents: 68
diff changeset
3323 test_lexer_string_locations_raw_string_one_line (const line_table_case &case_)
kono
parents: 68
diff changeset
3324 {
kono
parents: 68
diff changeset
3325 /* .....................00.0000000111111111122.
kono
parents: 68
diff changeset
3326 .....................12.3456789012345678901. */
kono
parents: 68
diff changeset
3327 const char *content = ("R\"foo(0123456789)foo\"\n");
kono
parents: 68
diff changeset
3328 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3329
kono
parents: 68
diff changeset
3330 /* Verify that we get the expected token back. */
kono
parents: 68
diff changeset
3331 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3332 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3333
kono
parents: 68
diff changeset
3334 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
3335 cpp_string dst_string;
kono
parents: 68
diff changeset
3336 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
3337 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
3338 &dst_string, type);
kono
parents: 68
diff changeset
3339 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
3340 ASSERT_STREQ ("0123456789", (const char *)dst_string.text);
kono
parents: 68
diff changeset
3341 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
3342
kono
parents: 68
diff changeset
3343 if (!should_have_column_data_p (line_table->highest_location))
kono
parents: 68
diff changeset
3344 return;
kono
parents: 68
diff changeset
3345
kono
parents: 68
diff changeset
3346 /* 0-9, plus the nil terminator. */
kono
parents: 68
diff changeset
3347 ASSERT_NUM_SUBSTRING_RANGES (test, tok->src_loc, CPP_STRING, 11);
kono
parents: 68
diff changeset
3348 for (int i = 0; i < 11; i++)
kono
parents: 68
diff changeset
3349 ASSERT_CHAR_AT_RANGE (test, tok->src_loc, CPP_STRING,
kono
parents: 68
diff changeset
3350 i, 1, 7 + i, 7 + i);
kono
parents: 68
diff changeset
3351 }
kono
parents: 68
diff changeset
3352
kono
parents: 68
diff changeset
3353 /* Test of locations within a raw string that contains a newline. */
kono
parents: 68
diff changeset
3354
kono
parents: 68
diff changeset
3355 static void
kono
parents: 68
diff changeset
3356 test_lexer_string_locations_raw_string_multiline (const line_table_case &case_)
kono
parents: 68
diff changeset
3357 {
kono
parents: 68
diff changeset
3358 /* .....................00.0000.
kono
parents: 68
diff changeset
3359 .....................12.3456. */
kono
parents: 68
diff changeset
3360 const char *content = ("R\"foo(\n"
kono
parents: 68
diff changeset
3361 /* .....................00000.
kono
parents: 68
diff changeset
3362 .....................12345. */
kono
parents: 68
diff changeset
3363 "hello\n"
kono
parents: 68
diff changeset
3364 "world\n"
kono
parents: 68
diff changeset
3365 /* .....................00000.
kono
parents: 68
diff changeset
3366 .....................12345. */
kono
parents: 68
diff changeset
3367 ")foo\"\n");
kono
parents: 68
diff changeset
3368 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3369
kono
parents: 68
diff changeset
3370 /* Verify that we get the expected token back. */
kono
parents: 68
diff changeset
3371 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3372 ASSERT_EQ (tok->type, CPP_STRING);
kono
parents: 68
diff changeset
3373
kono
parents: 68
diff changeset
3374 /* Verify that cpp_interpret_string works. */
kono
parents: 68
diff changeset
3375 cpp_string dst_string;
kono
parents: 68
diff changeset
3376 const enum cpp_ttype type = CPP_STRING;
kono
parents: 68
diff changeset
3377 bool result = cpp_interpret_string (test.m_parser, &tok->val.str, 1,
kono
parents: 68
diff changeset
3378 &dst_string, type);
kono
parents: 68
diff changeset
3379 ASSERT_TRUE (result);
kono
parents: 68
diff changeset
3380 ASSERT_STREQ ("\nhello\nworld\n", (const char *)dst_string.text);
kono
parents: 68
diff changeset
3381 free (const_cast <unsigned char *> (dst_string.text));
kono
parents: 68
diff changeset
3382
kono
parents: 68
diff changeset
3383 if (!should_have_column_data_p (line_table->highest_location))
kono
parents: 68
diff changeset
3384 return;
kono
parents: 68
diff changeset
3385
kono
parents: 68
diff changeset
3386 /* Currently we don't support locations within raw strings that
kono
parents: 68
diff changeset
3387 contain newlines. */
kono
parents: 68
diff changeset
3388 ASSERT_HAS_NO_SUBSTRING_RANGES (test, tok->src_loc, tok->type,
kono
parents: 68
diff changeset
3389 "range endpoints are on different lines");
kono
parents: 68
diff changeset
3390 }
kono
parents: 68
diff changeset
3391
kono
parents: 68
diff changeset
3392 /* Test of parsing an unterminated raw string. */
kono
parents: 68
diff changeset
3393
kono
parents: 68
diff changeset
3394 static void
kono
parents: 68
diff changeset
3395 test_lexer_string_locations_raw_string_unterminated (const line_table_case &case_)
kono
parents: 68
diff changeset
3396 {
kono
parents: 68
diff changeset
3397 const char *content = "R\"ouch()ouCh\" /* etc */";
kono
parents: 68
diff changeset
3398
kono
parents: 68
diff changeset
3399 lexer_error_sink errors;
kono
parents: 68
diff changeset
3400 lexer_test test (case_, content, &errors);
kono
parents: 68
diff changeset
3401 test.m_implicitly_expect_EOF = false;
kono
parents: 68
diff changeset
3402
kono
parents: 68
diff changeset
3403 /* Attempt to parse the raw string. */
kono
parents: 68
diff changeset
3404 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3405 ASSERT_EQ (tok->type, CPP_EOF);
kono
parents: 68
diff changeset
3406
kono
parents: 68
diff changeset
3407 ASSERT_EQ (1, errors.m_errors.length ());
kono
parents: 68
diff changeset
3408 /* We expect the message "unterminated raw string"
kono
parents: 68
diff changeset
3409 in the "cpplib" translation domain.
kono
parents: 68
diff changeset
3410 It's not clear that dgettext is available on all supported hosts,
kono
parents: 68
diff changeset
3411 so this assertion is commented-out for now.
kono
parents: 68
diff changeset
3412 ASSERT_STREQ (dgettext ("cpplib", "unterminated raw string"),
kono
parents: 68
diff changeset
3413 errors.m_errors[0]);
kono
parents: 68
diff changeset
3414 */
kono
parents: 68
diff changeset
3415 }
kono
parents: 68
diff changeset
3416
kono
parents: 68
diff changeset
3417 /* Test of lexing char constants. */
kono
parents: 68
diff changeset
3418
kono
parents: 68
diff changeset
3419 static void
kono
parents: 68
diff changeset
3420 test_lexer_char_constants (const line_table_case &case_)
kono
parents: 68
diff changeset
3421 {
kono
parents: 68
diff changeset
3422 /* Various char constants.
kono
parents: 68
diff changeset
3423 .....................0000000001111111111.22222222223.
kono
parents: 68
diff changeset
3424 .....................1234567890123456789.01234567890. */
kono
parents: 68
diff changeset
3425 const char *content = (" 'a'\n"
kono
parents: 68
diff changeset
3426 " u'a'\n"
kono
parents: 68
diff changeset
3427 " U'a'\n"
kono
parents: 68
diff changeset
3428 " L'a'\n"
kono
parents: 68
diff changeset
3429 " 'abc'\n");
kono
parents: 68
diff changeset
3430 lexer_test test (case_, content, NULL);
kono
parents: 68
diff changeset
3431
kono
parents: 68
diff changeset
3432 /* Verify that we get the expected tokens back. */
kono
parents: 68
diff changeset
3433 /* 'a'. */
kono
parents: 68
diff changeset
3434 const cpp_token *tok = test.get_token ();
kono
parents: 68
diff changeset
3435 ASSERT_EQ (tok->type, CPP_CHAR);
kono
parents: 68
diff changeset
3436 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "'a'");
kono
parents: 68
diff changeset
3437
kono
parents: 68
diff changeset
3438 unsigned int chars_seen;
kono
parents: 68
diff changeset
3439 int unsignedp;
kono
parents: 68
diff changeset
3440 cppchar_t cc = cpp_interpret_charconst (test.m_parser, tok,
kono
parents: 68
diff changeset
3441 &chars_seen, &unsignedp);
kono
parents: 68
diff changeset
3442 ASSERT_EQ (cc, 'a');
kono
parents: 68
diff changeset
3443 ASSERT_EQ (chars_seen, 1);
kono
parents: 68
diff changeset
3444
kono
parents: 68
diff changeset
3445 /* u'a'. */
kono
parents: 68
diff changeset
3446 tok = test.get_token ();
kono
parents: 68
diff changeset
3447 ASSERT_EQ (tok->type, CPP_CHAR16);
kono
parents: 68
diff changeset
3448 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "u'a'");
kono
parents: 68
diff changeset
3449
kono
parents: 68
diff changeset
3450 /* U'a'. */
kono
parents: 68
diff changeset
3451 tok = test.get_token ();
kono
parents: 68
diff changeset
3452 ASSERT_EQ (tok->type, CPP_CHAR32);
kono
parents: 68
diff changeset
3453 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "U'a'");
kono
parents: 68
diff changeset
3454
kono
parents: 68
diff changeset
3455 /* L'a'. */
kono
parents: 68
diff changeset
3456 tok = test.get_token ();
kono
parents: 68
diff changeset
3457 ASSERT_EQ (tok->type, CPP_WCHAR);
kono
parents: 68
diff changeset
3458 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "L'a'");
kono
parents: 68
diff changeset
3459
kono
parents: 68
diff changeset
3460 /* 'abc' (c-char-sequence). */
kono
parents: 68
diff changeset
3461 tok = test.get_token ();
kono
parents: 68
diff changeset
3462 ASSERT_EQ (tok->type, CPP_CHAR);
kono
parents: 68
diff changeset
3463 ASSERT_TOKEN_AS_TEXT_EQ (test.m_parser, tok, "'abc'");
kono
parents: 68
diff changeset
3464 }
kono
parents: 68
diff changeset
3465 /* A table of interesting location_t values, giving one axis of our test
kono
parents: 68
diff changeset
3466 matrix. */
kono
parents: 68
diff changeset
3467
kono
parents: 68
diff changeset
3468 static const location_t boundary_locations[] = {
kono
parents: 68
diff changeset
3469 /* Zero means "don't override the default values for a new line_table". */
kono
parents: 68
diff changeset
3470 0,
kono
parents: 68
diff changeset
3471
kono
parents: 68
diff changeset
3472 /* An arbitrary non-zero value that isn't close to one of
kono
parents: 68
diff changeset
3473 the boundary values below. */
kono
parents: 68
diff changeset
3474 0x10000,
kono
parents: 68
diff changeset
3475
kono
parents: 68
diff changeset
3476 /* Values near LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES. */
kono
parents: 68
diff changeset
3477 LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES - 0x100,
kono
parents: 68
diff changeset
3478 LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES - 1,
kono
parents: 68
diff changeset
3479 LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES,
kono
parents: 68
diff changeset
3480 LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 1,
kono
parents: 68
diff changeset
3481 LINE_MAP_MAX_LOCATION_WITH_PACKED_RANGES + 0x100,
kono
parents: 68
diff changeset
3482
kono
parents: 68
diff changeset
3483 /* Values near LINE_MAP_MAX_LOCATION_WITH_COLS. */
kono
parents: 68
diff changeset
3484 LINE_MAP_MAX_LOCATION_WITH_COLS - 0x100,
kono
parents: 68
diff changeset
3485 LINE_MAP_MAX_LOCATION_WITH_COLS - 1,
kono
parents: 68
diff changeset
3486 LINE_MAP_MAX_LOCATION_WITH_COLS,
kono
parents: 68
diff changeset
3487 LINE_MAP_MAX_LOCATION_WITH_COLS + 1,
kono
parents: 68
diff changeset
3488 LINE_MAP_MAX_LOCATION_WITH_COLS + 0x100,
kono
parents: 68
diff changeset
3489 };
kono
parents: 68
diff changeset
3490
kono
parents: 68
diff changeset
3491 /* Run TESTCASE multiple times, once for each case in our test matrix. */
kono
parents: 68
diff changeset
3492
kono
parents: 68
diff changeset
3493 void
kono
parents: 68
diff changeset
3494 for_each_line_table_case (void (*testcase) (const line_table_case &))
kono
parents: 68
diff changeset
3495 {
kono
parents: 68
diff changeset
3496 /* As noted above in the description of struct line_table_case,
kono
parents: 68
diff changeset
3497 we want to explore a test matrix of interesting line_table
kono
parents: 68
diff changeset
3498 situations, running various selftests for each case within the
kono
parents: 68
diff changeset
3499 matrix. */
kono
parents: 68
diff changeset
3500
kono
parents: 68
diff changeset
3501 /* Run all tests with:
kono
parents: 68
diff changeset
3502 (a) line_table->default_range_bits == 0, and
kono
parents: 68
diff changeset
3503 (b) line_table->default_range_bits == 5. */
kono
parents: 68
diff changeset
3504 int num_cases_tested = 0;
kono
parents: 68
diff changeset
3505 for (int default_range_bits = 0; default_range_bits <= 5;
kono
parents: 68
diff changeset
3506 default_range_bits += 5)
kono
parents: 68
diff changeset
3507 {
kono
parents: 68
diff changeset
3508 /* ...and use each of the "interesting" location values as
kono
parents: 68
diff changeset
3509 the starting location within line_table. */
kono
parents: 68
diff changeset
3510 const int num_boundary_locations
kono
parents: 68
diff changeset
3511 = sizeof (boundary_locations) / sizeof (boundary_locations[0]);
kono
parents: 68
diff changeset
3512 for (int loc_idx = 0; loc_idx < num_boundary_locations; loc_idx++)
kono
parents: 68
diff changeset
3513 {
kono
parents: 68
diff changeset
3514 line_table_case c (default_range_bits, boundary_locations[loc_idx]);
kono
parents: 68
diff changeset
3515
kono
parents: 68
diff changeset
3516 testcase (c);
kono
parents: 68
diff changeset
3517
kono
parents: 68
diff changeset
3518 num_cases_tested++;
kono
parents: 68
diff changeset
3519 }
kono
parents: 68
diff changeset
3520 }
kono
parents: 68
diff changeset
3521
kono
parents: 68
diff changeset
3522 /* Verify that we fully covered the test matrix. */
kono
parents: 68
diff changeset
3523 ASSERT_EQ (num_cases_tested, 2 * 12);
kono
parents: 68
diff changeset
3524 }
kono
parents: 68
diff changeset
3525
kono
parents: 68
diff changeset
3526 /* Run all of the selftests within this file. */
kono
parents: 68
diff changeset
3527
kono
parents: 68
diff changeset
3528 void
kono
parents: 68
diff changeset
3529 input_c_tests ()
kono
parents: 68
diff changeset
3530 {
kono
parents: 68
diff changeset
3531 test_should_have_column_data_p ();
kono
parents: 68
diff changeset
3532 test_unknown_location ();
kono
parents: 68
diff changeset
3533 test_builtins ();
kono
parents: 68
diff changeset
3534 for_each_line_table_case (test_make_location_nonpure_range_endpoints);
kono
parents: 68
diff changeset
3535
kono
parents: 68
diff changeset
3536 for_each_line_table_case (test_accessing_ordinary_linemaps);
kono
parents: 68
diff changeset
3537 for_each_line_table_case (test_lexer);
kono
parents: 68
diff changeset
3538 for_each_line_table_case (test_lexer_string_locations_simple);
kono
parents: 68
diff changeset
3539 for_each_line_table_case (test_lexer_string_locations_ebcdic);
kono
parents: 68
diff changeset
3540 for_each_line_table_case (test_lexer_string_locations_hex);
kono
parents: 68
diff changeset
3541 for_each_line_table_case (test_lexer_string_locations_oct);
kono
parents: 68
diff changeset
3542 for_each_line_table_case (test_lexer_string_locations_letter_escape_1);
kono
parents: 68
diff changeset
3543 for_each_line_table_case (test_lexer_string_locations_letter_escape_2);
kono
parents: 68
diff changeset
3544 for_each_line_table_case (test_lexer_string_locations_ucn4);
kono
parents: 68
diff changeset
3545 for_each_line_table_case (test_lexer_string_locations_ucn8);
kono
parents: 68
diff changeset
3546 for_each_line_table_case (test_lexer_string_locations_wide_string);
kono
parents: 68
diff changeset
3547 for_each_line_table_case (test_lexer_string_locations_string16);
kono
parents: 68
diff changeset
3548 for_each_line_table_case (test_lexer_string_locations_string32);
kono
parents: 68
diff changeset
3549 for_each_line_table_case (test_lexer_string_locations_u8);
kono
parents: 68
diff changeset
3550 for_each_line_table_case (test_lexer_string_locations_utf8_source);
kono
parents: 68
diff changeset
3551 for_each_line_table_case (test_lexer_string_locations_concatenation_1);
kono
parents: 68
diff changeset
3552 for_each_line_table_case (test_lexer_string_locations_concatenation_2);
kono
parents: 68
diff changeset
3553 for_each_line_table_case (test_lexer_string_locations_concatenation_3);
kono
parents: 68
diff changeset
3554 for_each_line_table_case (test_lexer_string_locations_macro);
kono
parents: 68
diff changeset
3555 for_each_line_table_case (test_lexer_string_locations_stringified_macro_argument);
kono
parents: 68
diff changeset
3556 for_each_line_table_case (test_lexer_string_locations_non_string);
kono
parents: 68
diff changeset
3557 for_each_line_table_case (test_lexer_string_locations_long_line);
kono
parents: 68
diff changeset
3558 for_each_line_table_case (test_lexer_string_locations_raw_string_one_line);
kono
parents: 68
diff changeset
3559 for_each_line_table_case (test_lexer_string_locations_raw_string_multiline);
kono
parents: 68
diff changeset
3560 for_each_line_table_case (test_lexer_string_locations_raw_string_unterminated);
kono
parents: 68
diff changeset
3561 for_each_line_table_case (test_lexer_char_constants);
kono
parents: 68
diff changeset
3562
kono
parents: 68
diff changeset
3563 test_reading_source_line ();
kono
parents: 68
diff changeset
3564 }
kono
parents: 68
diff changeset
3565
kono
parents: 68
diff changeset
3566 } // namespace selftest
kono
parents: 68
diff changeset
3567
kono
parents: 68
diff changeset
3568 #endif /* CHECKING_P */