File: | build/gcc/cp/module.cc |
Warning: | line 776, column 27 The result of the '<<' expression is undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* C++ modules. Experimental! | |||
2 | Copyright (C) 2017-2023 Free Software Foundation, Inc. | |||
3 | Written by Nathan Sidwell <nathan@acm.org> while at FaceBook | |||
4 | ||||
5 | This file is part of GCC. | |||
6 | ||||
7 | GCC is free software; you can redistribute it and/or modify it | |||
8 | under the terms of the GNU General Public License as published by | |||
9 | the Free Software Foundation; either version 3, or (at your option) | |||
10 | any later version. | |||
11 | ||||
12 | GCC is distributed in the hope that it will be useful, but | |||
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
15 | General Public License for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with GCC; see the file COPYING3. If not see | |||
19 | <http://www.gnu.org/licenses/>. */ | |||
20 | ||||
21 | /* Comments in this file have a non-negligible chance of being wrong | |||
22 | or at least inaccurate. Due to (a) my misunderstanding, (b) | |||
23 | ambiguities that I have interpretted differently to original intent | |||
24 | (c) changes in the specification, (d) my poor wording, (e) source | |||
25 | changes. */ | |||
26 | ||||
27 | /* (Incomplete) Design Notes | |||
28 | ||||
29 | A hash table contains all module names. Imported modules are | |||
30 | present in a modules array, which by construction places an | |||
31 | import's dependencies before the import itself. The single | |||
32 | exception is the current TU, which always occupies slot zero (even | |||
33 | when it is not a module). | |||
34 | ||||
35 | Imported decls occupy an entity_ary, an array of binding_slots, indexed | |||
36 | by importing module and index within that module. A flat index is | |||
37 | used, as each module reserves a contiguous range of indices. | |||
38 | Initially each slot indicates the CMI section containing the | |||
39 | streamed decl. When the decl is imported it will point to the decl | |||
40 | itself. | |||
41 | ||||
42 | Additionally each imported decl is mapped in the entity_map via its | |||
43 | DECL_UID to the flat index in the entity_ary. Thus we can locate | |||
44 | the index for any imported decl by using this map and then | |||
45 | de-flattening the index via a binary seach of the module vector. | |||
46 | Cross-module references are by (remapped) module number and | |||
47 | module-local index. | |||
48 | ||||
49 | Each importable DECL contains several flags. The simple set are | |||
50 | DECL_MODULE_EXPORT_P, DECL_MODULE_PURVIEW_P, DECL_MODULE_ATTACH_P | |||
51 | and DECL_MODULE_IMPORT_P. The first indicates whether it is | |||
52 | exported, the second whether it is in module or header-unit | |||
53 | purview. The third indicates it is attached to the named module in | |||
54 | whose purview it resides and the fourth indicates whether it was an | |||
55 | import into this TU or not. DECL_MODULE_ATTACH_P will be false for | |||
56 | all decls in a header-unit, and for those in a named module inside | |||
57 | a linkage declaration. | |||
58 | ||||
59 | The more detailed flags are DECL_MODULE_PARTITION_P, | |||
60 | DECL_MODULE_ENTITY_P. The first is set in a primary interface unit | |||
61 | on decls that were read from module partitions (these will have | |||
62 | DECL_MODULE_IMPORT_P set too). Such decls will be streamed out to | |||
63 | the primary's CMI. DECL_MODULE_ENTITY_P is set when an entity is | |||
64 | imported, even if it matched a non-imported entity. Such a decl | |||
65 | will not have DECL_MODULE_IMPORT_P set, even though it has an entry | |||
66 | in the entity map and array. | |||
67 | ||||
68 | Header units are module-like. | |||
69 | ||||
70 | For namespace-scope lookup, the decls for a particular module are | |||
71 | held located in a sparse array hanging off the binding of the name. | |||
72 | This is partitioned into two: a few fixed slots at the start | |||
73 | followed by the sparse slots afterwards. By construction we only | |||
74 | need to append new slots to the end -- there is never a need to | |||
75 | insert in the middle. The fixed slots are MODULE_SLOT_CURRENT for | |||
76 | the current TU (regardless of whether it is a module or not), | |||
77 | MODULE_SLOT_GLOBAL and MODULE_SLOT_PARTITION. These latter two | |||
78 | slots are used for merging entities across the global module and | |||
79 | module partitions respectively. MODULE_SLOT_PARTITION is only | |||
80 | present in a module. Neither of those two slots is searched during | |||
81 | name lookup -- they are internal use only. This vector is created | |||
82 | lazily once we require it, if there is only a declaration from the | |||
83 | current TU, a regular binding is present. It is converted on | |||
84 | demand. | |||
85 | ||||
86 | OPTIMIZATION: Outside of the current TU, we only need ADL to work. | |||
87 | We could optimize regular lookup for the current TU by glomming all | |||
88 | the visible decls on its slot. Perhaps wait until design is a | |||
89 | little more settled though. | |||
90 | ||||
91 | There is only one instance of each extern-linkage namespace. It | |||
92 | appears in every module slot that makes it visible. It also | |||
93 | appears in MODULE_SLOT_GLOBAL. (It is an ODR violation if they | |||
94 | collide with some other global module entity.) We also have an | |||
95 | optimization that shares the slot for adjacent modules that declare | |||
96 | the same such namespace. | |||
97 | ||||
98 | A module interface compilation produces a Compiled Module Interface | |||
99 | (CMI). The format used is Encapsulated Lazy Records Of Numbered | |||
100 | Declarations, which is essentially ELF's section encapsulation. (As | |||
101 | all good nerds are aware, Elrond is half Elf.) Some sections are | |||
102 | named, and contain information about the module as a whole (indices | |||
103 | etc), and other sections are referenced by number. Although I | |||
104 | don't defend against actively hostile CMIs, there is some | |||
105 | checksumming involved to verify data integrity. When dumping out | |||
106 | an interface, we generate a graph of all the | |||
107 | independently-redeclarable DECLS that are needed, and the decls | |||
108 | they reference. From that we determine the strongly connected | |||
109 | components (SCC) within this TU. Each SCC is dumped to a separate | |||
110 | numbered section of the CMI. We generate a binding table section, | |||
111 | mapping each namespace&name to a defining section. This allows | |||
112 | lazy loading. | |||
113 | ||||
114 | Lazy loading employs mmap to map a read-only image of the CMI. | |||
115 | It thus only occupies address space and is paged in on demand, | |||
116 | backed by the CMI file itself. If mmap is unavailable, regular | |||
117 | FILEIO is used. Also, there's a bespoke ELF reader/writer here, | |||
118 | which implements just the section table and sections (including | |||
119 | string sections) of a 32-bit ELF in host byte-order. You can of | |||
120 | course inspect it with readelf. I figured 32-bit is sufficient, | |||
121 | for a single module. I detect running out of section numbers, but | |||
122 | do not implement the ELF overflow mechanism. At least you'll get | |||
123 | an error if that happens. | |||
124 | ||||
125 | We do not separate declarations and definitions. My guess is that | |||
126 | if you refer to the declaration, you'll also need the definition | |||
127 | (template body, inline function, class definition etc). But this | |||
128 | does mean we can get larger SCCs than if we separated them. It is | |||
129 | unclear whether this is a win or not. | |||
130 | ||||
131 | Notice that we embed section indices into the contents of other | |||
132 | sections. Thus random manipulation of the CMI file by ELF tools | |||
133 | may well break it. The kosher way would probably be to introduce | |||
134 | indirection via section symbols, but that would require defining a | |||
135 | relocation type. | |||
136 | ||||
137 | Notice that lazy loading of one module's decls can cause lazy | |||
138 | loading of other decls in the same or another module. Clearly we | |||
139 | want to avoid loops. In a correct program there can be no loops in | |||
140 | the module dependency graph, and the above-mentioned SCC algorithm | |||
141 | places all intra-module circular dependencies in the same SCC. It | |||
142 | also orders the SCCs wrt each other, so dependent SCCs come first. | |||
143 | As we load dependent modules first, we know there can be no | |||
144 | reference to a higher-numbered module, and because we write out | |||
145 | dependent SCCs first, likewise for SCCs within the module. This | |||
146 | allows us to immediately detect broken references. When loading, | |||
147 | we must ensure the rest of the compiler doesn't cause some | |||
148 | unconnected load to occur (for instance, instantiate a template). | |||
149 | ||||
150 | Classes used: | |||
151 | ||||
152 | dumper - logger | |||
153 | ||||
154 | data - buffer | |||
155 | ||||
156 | bytes - data streamer | |||
157 | bytes_in : bytes - scalar reader | |||
158 | bytes_out : bytes - scalar writer | |||
159 | ||||
160 | elf - ELROND format | |||
161 | elf_in : elf - ELROND reader | |||
162 | elf_out : elf - ELROND writer | |||
163 | ||||
164 | trees_in : bytes_in - tree reader | |||
165 | trees_out : bytes_out - tree writer | |||
166 | ||||
167 | depset - dependency set | |||
168 | depset::hash - hash table of depsets | |||
169 | depset::tarjan - SCC determinator | |||
170 | ||||
171 | uidset<T> - set T's related to a UID | |||
172 | uidset<T>::hash hash table of uidset<T> | |||
173 | ||||
174 | loc_spans - location map data | |||
175 | ||||
176 | module_state - module object | |||
177 | ||||
178 | slurping - data needed during loading | |||
179 | ||||
180 | macro_import - imported macro data | |||
181 | macro_export - exported macro data | |||
182 | ||||
183 | The ELROND objects use mmap, for both reading and writing. If mmap | |||
184 | is unavailable, fileno IO is used to read and write blocks of data. | |||
185 | ||||
186 | The mapper object uses fileno IO to communicate with the server or | |||
187 | program. */ | |||
188 | ||||
189 | /* In expermental (trunk) sources, MODULE_VERSION is a #define passed | |||
190 | in from the Makefile. It records the modification date of the | |||
191 | source directory -- that's the only way to stay sane. In release | |||
192 | sources, we (plan to) use the compiler's major.minor versioning. | |||
193 | While the format might not change between at minor versions, it | |||
194 | seems simplest to tie the two together. There's no concept of | |||
195 | inter-version compatibility. */ | |||
196 | #define IS_EXPERIMENTAL(V)((V) >= (1U << 20)) ((V) >= (1U << 20)) | |||
197 | #define MODULE_MAJOR(V)((V) / 10000) ((V) / 10000) | |||
198 | #define MODULE_MINOR(V)((V) % 10000) ((V) % 10000) | |||
199 | #define EXPERIMENT(A,B)((((2301211953U)) >= (1U << 20)) ? (A) : (B)) (IS_EXPERIMENTAL (MODULE_VERSION)(((2301211953U)) >= (1U << 20)) ? (A) : (B)) | |||
200 | #ifndef MODULE_VERSION(2301211953U) | |||
201 | #include "bversion.h" | |||
202 | #define MODULE_VERSION(2301211953U) (BUILDING_GCC_MAJOR13 * 10000U + BUILDING_GCC_MINOR0) | |||
203 | #elif !IS_EXPERIMENTAL (MODULE_VERSION)(((2301211953U)) >= (1U << 20)) | |||
204 | #error "This is not the version I was looking for." | |||
205 | #endif | |||
206 | ||||
207 | #define _DEFAULT_SOURCE1 1 /* To get TZ field of struct tm, if available. */ | |||
208 | #include "config.h" | |||
209 | #define INCLUDE_MEMORY | |||
210 | #define INCLUDE_STRING | |||
211 | #define INCLUDE_VECTOR | |||
212 | #include "system.h" | |||
213 | #include "coretypes.h" | |||
214 | #include "cp-tree.h" | |||
215 | #include "timevar.h" | |||
216 | #include "stringpool.h" | |||
217 | #include "dumpfile.h" | |||
218 | #include "bitmap.h" | |||
219 | #include "cgraph.h" | |||
220 | #include "tree-iterator.h" | |||
221 | #include "cpplib.h" | |||
222 | #include "mkdeps.h" | |||
223 | #include "incpath.h" | |||
224 | #include "libiberty.h" | |||
225 | #include "stor-layout.h" | |||
226 | #include "version.h" | |||
227 | #include "tree-diagnostic.h" | |||
228 | #include "toplev.h" | |||
229 | #include "opts.h" | |||
230 | #include "attribs.h" | |||
231 | #include "intl.h" | |||
232 | #include "langhooks.h" | |||
233 | /* This TU doesn't need or want to see the networking. */ | |||
234 | #define CODY_NETWORKING0 0 | |||
235 | #include "mapper-client.h" | |||
236 | ||||
237 | #if 0 // 1 for testing no mmap | |||
238 | #define MAPPED_READING1 0 | |||
239 | #define MAPPED_WRITING1 0 | |||
240 | #else | |||
241 | #if HAVE_MMAP_FILE1 && _POSIX_MAPPED_FILES200809L > 0 | |||
242 | /* mmap, munmap. */ | |||
243 | #define MAPPED_READING1 1 | |||
244 | #if HAVE_SYSCONF1 && defined (_SC_PAGE_SIZE_SC_PAGESIZE) | |||
245 | /* msync, sysconf (_SC_PAGE_SIZE), ftruncate */ | |||
246 | /* posix_fallocate used if available. */ | |||
247 | #define MAPPED_WRITING1 1 | |||
248 | #else | |||
249 | #define MAPPED_WRITING1 0 | |||
250 | #endif | |||
251 | #else | |||
252 | #define MAPPED_READING1 0 | |||
253 | #define MAPPED_WRITING1 0 | |||
254 | #endif | |||
255 | #endif | |||
256 | ||||
257 | /* Some open(2) flag differences, what a colourful world it is! */ | |||
258 | #if defined (O_CLOEXEC02000000) | |||
259 | // OK | |||
260 | #elif defined (_O_NOINHERIT) | |||
261 | /* Windows' _O_NOINHERIT matches O_CLOEXEC flag */ | |||
262 | #define O_CLOEXEC02000000 _O_NOINHERIT | |||
263 | #else | |||
264 | #define O_CLOEXEC02000000 0 | |||
265 | #endif | |||
266 | #if defined (O_BINARY0) | |||
267 | // Ok? | |||
268 | #elif defined (_O_BINARY) | |||
269 | /* Windows' open(2) call defaults to text! */ | |||
270 | #define O_BINARY0 _O_BINARY | |||
271 | #else | |||
272 | #define O_BINARY0 0 | |||
273 | #endif | |||
274 | ||||
275 | static inline cpp_hashnode *cpp_node (tree id) | |||
276 | { | |||
277 | return CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (id))((cpp_hashnode *) ((&((struct tree_identifier *) (id))-> id))); | |||
278 | } | |||
279 | ||||
280 | static inline tree identifier (const cpp_hashnode *node) | |||
281 | { | |||
282 | /* HT_NODE() expands to node->ident that HT_IDENT_TO_GCC_IDENT() | |||
283 | then subtracts a nonzero constant, deriving a pointer to | |||
284 | a different member than ident. That's strictly undefined | |||
285 | and detected by -Warray-bounds. Suppress it. See PR 101372. */ | |||
286 | #pragma GCC diagnostic push | |||
287 | #pragma GCC diagnostic ignored "-Warray-bounds" | |||
288 | return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node)))((tree) ((char *) ((&(const_cast<cpp_hashnode *> (node ))->ident)) - sizeof (struct tree_common))); | |||
289 | #pragma GCC diagnostic pop | |||
290 | } | |||
291 | ||||
292 | /* Id for dumping module information. */ | |||
293 | int module_dump_id; | |||
294 | ||||
295 | /* We have a special module owner. */ | |||
296 | #define MODULE_UNKNOWN(~0U) (~0U) /* Not yet known. */ | |||
297 | ||||
298 | /* Prefix for section names. */ | |||
299 | #define MOD_SNAME_PFX".gnu.c++" ".gnu.c++" | |||
300 | ||||
301 | /* Format a version for user consumption. */ | |||
302 | ||||
303 | typedef char verstr_t[32]; | |||
304 | static void | |||
305 | version2string (unsigned version, verstr_t &out) | |||
306 | { | |||
307 | unsigned major = MODULE_MAJOR (version)((version) / 10000); | |||
308 | unsigned minor = MODULE_MINOR (version)((version) % 10000); | |||
309 | ||||
310 | if (IS_EXPERIMENTAL (version)((version) >= (1U << 20))) | |||
311 | sprintf (out, "%04u/%02u/%02u-%02u:%02u%s", | |||
312 | 2000 + major / 10000, (major / 100) % 100, (major % 100), | |||
313 | minor / 100, minor % 100, | |||
314 | EXPERIMENT ("", " (experimental)")((((2301211953U)) >= (1U << 20)) ? ("") : (" (experimental)" ))); | |||
315 | else | |||
316 | sprintf (out, "%u.%u", major, minor); | |||
317 | } | |||
318 | ||||
319 | /* Include files to note translation for. */ | |||
320 | static vec<const char *, va_heap, vl_embed> *note_includes; | |||
321 | ||||
322 | /* Modules to note CMI pathames. */ | |||
323 | static vec<const char *, va_heap, vl_embed> *note_cmis; | |||
324 | ||||
325 | /* Traits to hash an arbitrary pointer. Entries are not deletable, | |||
326 | and removal is a noop (removal needed upon destruction). */ | |||
327 | template <typename T> | |||
328 | struct nodel_ptr_hash : pointer_hash<T>, typed_noop_remove <T *> { | |||
329 | /* Nothing is deletable. Everything is insertable. */ | |||
330 | static bool is_deleted (T *) { return false; } | |||
331 | static void mark_deleted (T *) { gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 331, __FUNCTION__)); } | |||
332 | }; | |||
333 | ||||
334 | /* Map from pointer to signed integer. */ | |||
335 | typedef simple_hashmap_traits<nodel_ptr_hash<void>, int> ptr_int_traits; | |||
336 | typedef hash_map<void *,signed,ptr_int_traits> ptr_int_hash_map; | |||
337 | ||||
338 | /********************************************************************/ | |||
339 | /* Basic streaming & ELF. Serialization is usually via mmap. For | |||
340 | writing we slide a buffer over the output file, syncing it | |||
341 | approproiately. For reading we simply map the whole file (as a | |||
342 | file-backed read-only map -- it's just address space, leaving the | |||
343 | OS pager to deal with getting the data to us). Some buffers need | |||
344 | to be more conventional malloc'd contents. */ | |||
345 | ||||
346 | /* Variable length buffer. */ | |||
347 | ||||
348 | class data { | |||
349 | public: | |||
350 | class allocator { | |||
351 | public: | |||
352 | /* Tools tend to moan if the dtor's not virtual. */ | |||
353 | virtual ~allocator () {} | |||
354 | ||||
355 | public: | |||
356 | void grow (data &obj, unsigned needed, bool exact); | |||
357 | void shrink (data &obj); | |||
358 | ||||
359 | public: | |||
360 | virtual char *grow (char *ptr, unsigned needed); | |||
361 | virtual void shrink (char *ptr); | |||
362 | }; | |||
363 | ||||
364 | public: | |||
365 | char *buffer; /* Buffer being transferred. */ | |||
366 | /* Although size_t would be the usual size, we know we never get | |||
367 | more than 4GB of buffer -- because that's the limit of the | |||
368 | encapsulation format. And if you need bigger imports, you're | |||
369 | doing it wrong. */ | |||
370 | unsigned size; /* Allocated size of buffer. */ | |||
371 | unsigned pos; /* Position in buffer. */ | |||
372 | ||||
373 | public: | |||
374 | data () | |||
375 | :buffer (NULLnullptr), size (0), pos (0) | |||
376 | { | |||
377 | } | |||
378 | ~data () | |||
379 | { | |||
380 | /* Make sure the derived and/or using class know what they're | |||
381 | doing. */ | |||
382 | gcc_checking_assert (!buffer)((void)(!(!buffer) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 382, __FUNCTION__), 0 : 0)); | |||
383 | } | |||
384 | ||||
385 | protected: | |||
386 | char *use (unsigned count) | |||
387 | { | |||
388 | if (size < pos + count) | |||
389 | return NULLnullptr; | |||
390 | char *res = &buffer[pos]; | |||
391 | pos += count; | |||
392 | return res; | |||
393 | } | |||
394 | ||||
395 | public: | |||
396 | void unuse (unsigned count) | |||
397 | { | |||
398 | pos -= count; | |||
399 | } | |||
400 | ||||
401 | public: | |||
402 | static allocator simple_memory; | |||
403 | }; | |||
404 | ||||
405 | /* The simple data allocator. */ | |||
406 | data::allocator data::simple_memory; | |||
407 | ||||
408 | /* Grow buffer to at least size NEEDED. */ | |||
409 | ||||
410 | void | |||
411 | data::allocator::grow (data &obj, unsigned needed, bool exact) | |||
412 | { | |||
413 | gcc_checking_assert (needed ? needed > obj.size : !obj.size)((void)(!(needed ? needed > obj.size : !obj.size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 413, __FUNCTION__), 0 : 0)); | |||
414 | if (!needed) | |||
415 | /* Pick a default size. */ | |||
416 | needed = EXPERIMENT (100, 1000)((((2301211953U)) >= (1U << 20)) ? (100) : (1000)); | |||
417 | ||||
418 | if (!exact) | |||
419 | needed *= 2; | |||
420 | obj.buffer = grow (obj.buffer, needed); | |||
421 | if (obj.buffer) | |||
422 | obj.size = needed; | |||
423 | else | |||
424 | obj.pos = obj.size = 0; | |||
425 | } | |||
426 | ||||
427 | /* Free a buffer. */ | |||
428 | ||||
429 | void | |||
430 | data::allocator::shrink (data &obj) | |||
431 | { | |||
432 | shrink (obj.buffer); | |||
433 | obj.buffer = NULLnullptr; | |||
434 | obj.size = 0; | |||
435 | } | |||
436 | ||||
437 | char * | |||
438 | data::allocator::grow (char *ptr, unsigned needed) | |||
439 | { | |||
440 | return XRESIZEVAR (char, ptr, needed)((char *) xrealloc ((ptr), (needed))); | |||
441 | } | |||
442 | ||||
443 | void | |||
444 | data::allocator::shrink (char *ptr) | |||
445 | { | |||
446 | XDELETEVEC (ptr)free ((void*) (ptr)); | |||
447 | } | |||
448 | ||||
449 | /* Byte streamer base. Buffer with read/write position and smarts | |||
450 | for single bits. */ | |||
451 | ||||
452 | class bytes : public data { | |||
453 | public: | |||
454 | typedef data parent; | |||
455 | ||||
456 | protected: | |||
457 | uint32_t bit_val; /* Bit buffer. */ | |||
458 | unsigned bit_pos; /* Next bit in bit buffer. */ | |||
459 | ||||
460 | public: | |||
461 | bytes () | |||
462 | :parent (), bit_val (0), bit_pos (0) | |||
463 | {} | |||
464 | ~bytes () | |||
465 | { | |||
466 | } | |||
467 | ||||
468 | protected: | |||
469 | unsigned calc_crc (unsigned) const; | |||
470 | ||||
471 | protected: | |||
472 | /* Finish bit packet. Rewind the bytes not used. */ | |||
473 | unsigned bit_flush () | |||
474 | { | |||
475 | gcc_assert (bit_pos)((void)(!(bit_pos) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 475, __FUNCTION__), 0 : 0)); | |||
476 | unsigned bytes = (bit_pos + 7) / 8; | |||
477 | unuse (4 - bytes); | |||
478 | bit_pos = 0; | |||
479 | bit_val = 0; | |||
480 | return bytes; | |||
481 | } | |||
482 | }; | |||
483 | ||||
484 | /* Calculate the crc32 of the buffer. Note the CRC is stored in the | |||
485 | first 4 bytes, so don't include them. */ | |||
486 | ||||
487 | unsigned | |||
488 | bytes::calc_crc (unsigned l) const | |||
489 | { | |||
490 | unsigned crc = 0; | |||
491 | for (size_t ix = 4; ix < l; ix++) | |||
492 | crc = crc32_byte (crc, buffer[ix]); | |||
493 | return crc; | |||
494 | } | |||
495 | ||||
496 | class elf_in; | |||
497 | ||||
498 | /* Byte stream reader. */ | |||
499 | ||||
500 | class bytes_in : public bytes { | |||
501 | typedef bytes parent; | |||
502 | ||||
503 | protected: | |||
504 | bool overrun; /* Sticky read-too-much flag. */ | |||
505 | ||||
506 | public: | |||
507 | bytes_in () | |||
508 | : parent (), overrun (false) | |||
509 | { | |||
510 | } | |||
511 | ~bytes_in () | |||
512 | { | |||
513 | } | |||
514 | ||||
515 | public: | |||
516 | /* Begin reading a named section. */ | |||
517 | bool begin (location_t loc, elf_in *src, const char *name); | |||
518 | /* Begin reading a numbered section with optional name. */ | |||
519 | bool begin (location_t loc, elf_in *src, unsigned, const char * = NULLnullptr); | |||
520 | /* Complete reading a buffer. Propagate errors and return true on | |||
521 | success. */ | |||
522 | bool end (elf_in *src); | |||
523 | /* Return true if there is unread data. */ | |||
524 | bool more_p () const | |||
525 | { | |||
526 | return pos != size; | |||
527 | } | |||
528 | ||||
529 | public: | |||
530 | /* Start reading at OFFSET. */ | |||
531 | void random_access (unsigned offset) | |||
532 | { | |||
533 | if (offset > size) | |||
534 | set_overrun (); | |||
535 | pos = offset; | |||
536 | bit_pos = bit_val = 0; | |||
537 | } | |||
538 | ||||
539 | public: | |||
540 | void align (unsigned boundary) | |||
541 | { | |||
542 | if (unsigned pad = pos & (boundary - 1)) | |||
543 | read (boundary - pad); | |||
544 | } | |||
545 | ||||
546 | public: | |||
547 | const char *read (unsigned count) | |||
548 | { | |||
549 | char *ptr = use (count); | |||
550 | if (!ptr) | |||
551 | set_overrun (); | |||
552 | return ptr; | |||
553 | } | |||
554 | ||||
555 | public: | |||
556 | bool check_crc () const; | |||
557 | /* We store the CRC in the first 4 bytes, using host endianness. */ | |||
558 | unsigned get_crc () const | |||
559 | { | |||
560 | return *(const unsigned *)&buffer[0]; | |||
561 | } | |||
562 | ||||
563 | public: | |||
564 | /* Manipulate the overrun flag. */ | |||
565 | bool get_overrun () const | |||
566 | { | |||
567 | return overrun; | |||
568 | } | |||
569 | void set_overrun () | |||
570 | { | |||
571 | overrun = true; | |||
572 | } | |||
573 | ||||
574 | public: | |||
575 | unsigned u32 (); /* Read uncompressed integer. */ | |||
576 | ||||
577 | public: | |||
578 | bool b (); /* Read a bool. */ | |||
579 | void bflush (); /* Completed a block of bools. */ | |||
580 | ||||
581 | private: | |||
582 | void bfill (); /* Get the next block of bools. */ | |||
583 | ||||
584 | public: | |||
585 | int c (); /* Read a char. */ | |||
586 | int i (); /* Read a signed int. */ | |||
587 | unsigned u (); /* Read an unsigned int. */ | |||
588 | size_t z (); /* Read a size_t. */ | |||
589 | HOST_WIDE_INTlong wi (); /* Read a HOST_WIDE_INT. */ | |||
590 | unsigned HOST_WIDE_INTlong wu (); /* Read an unsigned HOST_WIDE_INT. */ | |||
591 | const char *str (size_t * = NULLnullptr); /* Read a string. */ | |||
592 | const void *buf (size_t); /* Read a fixed-length buffer. */ | |||
593 | cpp_hashnode *cpp_node (); /* Read a cpp node. */ | |||
594 | }; | |||
595 | ||||
596 | /* Verify the buffer's CRC is correct. */ | |||
597 | ||||
598 | bool | |||
599 | bytes_in::check_crc () const | |||
600 | { | |||
601 | if (size < 4) | |||
602 | return false; | |||
603 | ||||
604 | unsigned c_crc = calc_crc (size); | |||
605 | if (c_crc != get_crc ()) | |||
606 | return false; | |||
607 | ||||
608 | return true; | |||
609 | } | |||
610 | ||||
611 | class elf_out; | |||
612 | ||||
613 | /* Byte stream writer. */ | |||
614 | ||||
615 | class bytes_out : public bytes { | |||
616 | typedef bytes parent; | |||
617 | ||||
618 | public: | |||
619 | allocator *memory; /* Obtainer of memory. */ | |||
620 | ||||
621 | public: | |||
622 | bytes_out (allocator *memory) | |||
623 | : parent (), memory (memory) | |||
624 | { | |||
625 | } | |||
626 | ~bytes_out () | |||
627 | { | |||
628 | } | |||
629 | ||||
630 | public: | |||
631 | bool streaming_p () const | |||
632 | { | |||
633 | return memory != NULLnullptr; | |||
634 | } | |||
635 | ||||
636 | public: | |||
637 | void set_crc (unsigned *crc_ptr); | |||
638 | ||||
639 | public: | |||
640 | /* Begin writing, maybe reserve space for CRC. */ | |||
641 | void begin (bool need_crc = true); | |||
642 | /* Finish writing. Spill to section by number. */ | |||
643 | unsigned end (elf_out *, unsigned, unsigned *crc_ptr = NULLnullptr); | |||
644 | ||||
645 | public: | |||
646 | void align (unsigned boundary) | |||
647 | { | |||
648 | if (unsigned pad = pos & (boundary - 1)) | |||
649 | write (boundary - pad); | |||
650 | } | |||
651 | ||||
652 | public: | |||
653 | char *write (unsigned count, bool exact = false) | |||
654 | { | |||
655 | if (size < pos + count) | |||
656 | memory->grow (*this, pos + count, exact); | |||
657 | return use (count); | |||
658 | } | |||
659 | ||||
660 | public: | |||
661 | void u32 (unsigned); /* Write uncompressed integer. */ | |||
662 | ||||
663 | public: | |||
664 | void b (bool); /* Write bool. */ | |||
665 | void bflush (); /* Finish block of bools. */ | |||
666 | ||||
667 | public: | |||
668 | void c (unsigned char); /* Write unsigned char. */ | |||
669 | void i (int); /* Write signed int. */ | |||
670 | void u (unsigned); /* Write unsigned int. */ | |||
671 | void z (size_t s); /* Write size_t. */ | |||
672 | void wi (HOST_WIDE_INTlong); /* Write HOST_WIDE_INT. */ | |||
673 | void wu (unsigned HOST_WIDE_INTlong); /* Write unsigned HOST_WIDE_INT. */ | |||
674 | void str (const char *ptr) | |||
675 | { | |||
676 | str (ptr, strlen (ptr)); | |||
677 | } | |||
678 | void cpp_node (const cpp_hashnode *node) | |||
679 | { | |||
680 | str ((const char *)NODE_NAME (node)(((&(node)->ident))->str), NODE_LEN (node)(((&(node)->ident))->len)); | |||
681 | } | |||
682 | void str (const char *, size_t); /* Write string of known length. */ | |||
683 | void buf (const void *, size_t); /* Write fixed length buffer. */ | |||
684 | void *buf (size_t); /* Create a writable buffer */ | |||
685 | ||||
686 | public: | |||
687 | /* Format a NUL-terminated raw string. */ | |||
688 | void printf (const char *, ...) ATTRIBUTE_PRINTF_2__attribute__ ((__format__ (__printf__, 2, 3))) __attribute__ ((__nonnull__ (2))); | |||
689 | void print_time (const char *, const tm *, const char *); | |||
690 | ||||
691 | public: | |||
692 | /* Dump instrumentation. */ | |||
693 | static void instrument (); | |||
694 | ||||
695 | protected: | |||
696 | /* Instrumentation. */ | |||
697 | static unsigned spans[4]; | |||
698 | static unsigned lengths[4]; | |||
699 | static int is_set; | |||
700 | }; | |||
701 | ||||
702 | /* Instrumentation. */ | |||
703 | unsigned bytes_out::spans[4]; | |||
704 | unsigned bytes_out::lengths[4]; | |||
705 | int bytes_out::is_set = -1; | |||
706 | ||||
707 | /* If CRC_PTR non-null, set the CRC of the buffer. Mix the CRC into | |||
708 | that pointed to by CRC_PTR. */ | |||
709 | ||||
710 | void | |||
711 | bytes_out::set_crc (unsigned *crc_ptr) | |||
712 | { | |||
713 | if (crc_ptr) | |||
714 | { | |||
715 | gcc_checking_assert (pos >= 4)((void)(!(pos >= 4) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 715, __FUNCTION__), 0 : 0)); | |||
716 | ||||
717 | unsigned crc = calc_crc (pos); | |||
718 | unsigned accum = *crc_ptr; | |||
719 | /* Only mix the existing *CRC_PTR if it is non-zero. */ | |||
720 | accum = accum ? crc32_unsigned (accum, crc) : crc; | |||
721 | *crc_ptr = accum; | |||
722 | ||||
723 | /* Buffer will be sufficiently aligned. */ | |||
724 | *(unsigned *)buffer = crc; | |||
725 | } | |||
726 | } | |||
727 | ||||
728 | /* Finish a set of bools. */ | |||
729 | ||||
730 | void | |||
731 | bytes_out::bflush () | |||
732 | { | |||
733 | if (bit_pos) | |||
734 | { | |||
735 | u32 (bit_val); | |||
736 | lengths[2] += bit_flush (); | |||
737 | } | |||
738 | spans[2]++; | |||
739 | is_set = -1; | |||
740 | } | |||
741 | ||||
742 | void | |||
743 | bytes_in::bflush () | |||
744 | { | |||
745 | if (bit_pos) | |||
746 | bit_flush (); | |||
747 | } | |||
748 | ||||
749 | /* When reading, we don't know how many bools we'll read in. So read | |||
750 | 4 bytes-worth, and then rewind when flushing if we didn't need them | |||
751 | all. You can't have a block of bools closer than 4 bytes to the | |||
752 | end of the buffer. */ | |||
753 | ||||
754 | void | |||
755 | bytes_in::bfill () | |||
756 | { | |||
757 | bit_val = u32 (); | |||
758 | } | |||
759 | ||||
760 | /* Bools are packed into bytes. You cannot mix bools and non-bools. | |||
761 | You must call bflush before emitting another type. So batch your | |||
762 | bools. | |||
763 | ||||
764 | It may be worth optimizing for most bools being zero. Some kind of | |||
765 | run-length encoding? */ | |||
766 | ||||
767 | void | |||
768 | bytes_out::b (bool x) | |||
769 | { | |||
770 | if (is_set != x) | |||
771 | { | |||
772 | is_set = x; | |||
773 | spans[x]++; | |||
774 | } | |||
775 | lengths[x]++; | |||
776 | bit_val |= unsigned (x) << bit_pos++; | |||
| ||||
777 | if (bit_pos == 32) | |||
778 | { | |||
779 | u32 (bit_val); | |||
780 | lengths[2] += bit_flush (); | |||
781 | } | |||
782 | } | |||
783 | ||||
784 | bool | |||
785 | bytes_in::b () | |||
786 | { | |||
787 | if (!bit_pos) | |||
788 | bfill (); | |||
789 | bool v = (bit_val >> bit_pos++) & 1; | |||
790 | if (bit_pos == 32) | |||
791 | bit_flush (); | |||
792 | return v; | |||
793 | } | |||
794 | ||||
795 | /* Exactly 4 bytes. Used internally for bool packing and a few other | |||
796 | places. We can't simply use uint32_t because (a) alignment and | |||
797 | (b) we need little-endian for the bool streaming rewinding to make | |||
798 | sense. */ | |||
799 | ||||
800 | void | |||
801 | bytes_out::u32 (unsigned val) | |||
802 | { | |||
803 | if (char *ptr = write (4)) | |||
804 | { | |||
805 | ptr[0] = val; | |||
806 | ptr[1] = val >> 8; | |||
807 | ptr[2] = val >> 16; | |||
808 | ptr[3] = val >> 24; | |||
809 | } | |||
810 | } | |||
811 | ||||
812 | unsigned | |||
813 | bytes_in::u32 () | |||
814 | { | |||
815 | unsigned val = 0; | |||
816 | if (const char *ptr = read (4)) | |||
817 | { | |||
818 | val |= (unsigned char)ptr[0]; | |||
819 | val |= (unsigned char)ptr[1] << 8; | |||
820 | val |= (unsigned char)ptr[2] << 16; | |||
821 | val |= (unsigned char)ptr[3] << 24; | |||
822 | } | |||
823 | ||||
824 | return val; | |||
825 | } | |||
826 | ||||
827 | /* Chars are unsigned and written as single bytes. */ | |||
828 | ||||
829 | void | |||
830 | bytes_out::c (unsigned char v) | |||
831 | { | |||
832 | if (char *ptr = write (1)) | |||
833 | *ptr = v; | |||
834 | } | |||
835 | ||||
836 | int | |||
837 | bytes_in::c () | |||
838 | { | |||
839 | int v = 0; | |||
840 | if (const char *ptr = read (1)) | |||
841 | v = (unsigned char)ptr[0]; | |||
842 | return v; | |||
843 | } | |||
844 | ||||
845 | /* Ints 7-bit as a byte. Otherwise a 3bit count of following bytes in | |||
846 | big-endian form. 4 bits are in the first byte. */ | |||
847 | ||||
848 | void | |||
849 | bytes_out::i (int v) | |||
850 | { | |||
851 | if (char *ptr = write (1)) | |||
852 | { | |||
853 | if (v <= 0x3f && v >= -0x40) | |||
854 | *ptr = v & 0x7f; | |||
855 | else | |||
856 | { | |||
857 | unsigned bytes = 0; | |||
858 | int probe; | |||
859 | if (v >= 0) | |||
860 | for (probe = v >> 8; probe > 0x7; probe >>= 8) | |||
861 | bytes++; | |||
862 | else | |||
863 | for (probe = v >> 8; probe < -0x8; probe >>= 8) | |||
864 | bytes++; | |||
865 | *ptr = 0x80 | bytes << 4 | (probe & 0xf); | |||
866 | if ((ptr = write (++bytes))) | |||
867 | for (; bytes--; v >>= 8) | |||
868 | ptr[bytes] = v & 0xff; | |||
869 | } | |||
870 | } | |||
871 | } | |||
872 | ||||
873 | int | |||
874 | bytes_in::i () | |||
875 | { | |||
876 | int v = 0; | |||
877 | if (const char *ptr = read (1)) | |||
878 | { | |||
879 | v = *ptr & 0xff; | |||
880 | if (v & 0x80) | |||
881 | { | |||
882 | unsigned bytes = (v >> 4) & 0x7; | |||
883 | v &= 0xf; | |||
884 | if (v & 0x8) | |||
885 | v |= -1 ^ 0x7; | |||
886 | /* unsigned necessary due to left shifts of -ve values. */ | |||
887 | unsigned uv = unsigned (v); | |||
888 | if ((ptr = read (++bytes))) | |||
889 | while (bytes--) | |||
890 | uv = (uv << 8) | (*ptr++ & 0xff); | |||
891 | v = int (uv); | |||
892 | } | |||
893 | else if (v & 0x40) | |||
894 | v |= -1 ^ 0x3f; | |||
895 | } | |||
896 | ||||
897 | return v; | |||
898 | } | |||
899 | ||||
900 | void | |||
901 | bytes_out::u (unsigned v) | |||
902 | { | |||
903 | if (char *ptr = write (1)) | |||
904 | { | |||
905 | if (v <= 0x7f) | |||
906 | *ptr = v; | |||
907 | else | |||
908 | { | |||
909 | unsigned bytes = 0; | |||
910 | unsigned probe; | |||
911 | for (probe = v >> 8; probe > 0xf; probe >>= 8) | |||
912 | bytes++; | |||
913 | *ptr = 0x80 | bytes << 4 | probe; | |||
914 | if ((ptr = write (++bytes))) | |||
915 | for (; bytes--; v >>= 8) | |||
916 | ptr[bytes] = v & 0xff; | |||
917 | } | |||
918 | } | |||
919 | } | |||
920 | ||||
921 | unsigned | |||
922 | bytes_in::u () | |||
923 | { | |||
924 | unsigned v = 0; | |||
925 | ||||
926 | if (const char *ptr = read (1)) | |||
927 | { | |||
928 | v = *ptr & 0xff; | |||
929 | if (v & 0x80) | |||
930 | { | |||
931 | unsigned bytes = (v >> 4) & 0x7; | |||
932 | v &= 0xf; | |||
933 | if ((ptr = read (++bytes))) | |||
934 | while (bytes--) | |||
935 | v = (v << 8) | (*ptr++ & 0xff); | |||
936 | } | |||
937 | } | |||
938 | ||||
939 | return v; | |||
940 | } | |||
941 | ||||
942 | void | |||
943 | bytes_out::wi (HOST_WIDE_INTlong v) | |||
944 | { | |||
945 | if (char *ptr = write (1)) | |||
946 | { | |||
947 | if (v <= 0x3f && v >= -0x40) | |||
948 | *ptr = v & 0x7f; | |||
949 | else | |||
950 | { | |||
951 | unsigned bytes = 0; | |||
952 | HOST_WIDE_INTlong probe; | |||
953 | if (v >= 0) | |||
954 | for (probe = v >> 8; probe > 0x7; probe >>= 8) | |||
955 | bytes++; | |||
956 | else | |||
957 | for (probe = v >> 8; probe < -0x8; probe >>= 8) | |||
958 | bytes++; | |||
959 | *ptr = 0x80 | bytes << 4 | (probe & 0xf); | |||
960 | if ((ptr = write (++bytes))) | |||
961 | for (; bytes--; v >>= 8) | |||
962 | ptr[bytes] = v & 0xff; | |||
963 | } | |||
964 | } | |||
965 | } | |||
966 | ||||
967 | HOST_WIDE_INTlong | |||
968 | bytes_in::wi () | |||
969 | { | |||
970 | HOST_WIDE_INTlong v = 0; | |||
971 | if (const char *ptr = read (1)) | |||
972 | { | |||
973 | v = *ptr & 0xff; | |||
974 | if (v & 0x80) | |||
975 | { | |||
976 | unsigned bytes = (v >> 4) & 0x7; | |||
977 | v &= 0xf; | |||
978 | if (v & 0x8) | |||
979 | v |= -1 ^ 0x7; | |||
980 | /* unsigned necessary due to left shifts of -ve values. */ | |||
981 | unsigned HOST_WIDE_INTlong uv = (unsigned HOST_WIDE_INTlong) v; | |||
982 | if ((ptr = read (++bytes))) | |||
983 | while (bytes--) | |||
984 | uv = (uv << 8) | (*ptr++ & 0xff); | |||
985 | v = (HOST_WIDE_INTlong) uv; | |||
986 | } | |||
987 | else if (v & 0x40) | |||
988 | v |= -1 ^ 0x3f; | |||
989 | } | |||
990 | ||||
991 | return v; | |||
992 | } | |||
993 | ||||
994 | /* unsigned wide ints are just written as signed wide ints. */ | |||
995 | ||||
996 | inline void | |||
997 | bytes_out::wu (unsigned HOST_WIDE_INTlong v) | |||
998 | { | |||
999 | wi ((HOST_WIDE_INTlong) v); | |||
1000 | } | |||
1001 | ||||
1002 | inline unsigned HOST_WIDE_INTlong | |||
1003 | bytes_in::wu () | |||
1004 | { | |||
1005 | return (unsigned HOST_WIDE_INTlong) wi (); | |||
1006 | } | |||
1007 | ||||
1008 | /* size_t written as unsigned or unsigned wide int. */ | |||
1009 | ||||
1010 | inline void | |||
1011 | bytes_out::z (size_t s) | |||
1012 | { | |||
1013 | if (sizeof (s) == sizeof (unsigned)) | |||
1014 | u (s); | |||
1015 | else | |||
1016 | wu (s); | |||
1017 | } | |||
1018 | ||||
1019 | inline size_t | |||
1020 | bytes_in::z () | |||
1021 | { | |||
1022 | if (sizeof (size_t) == sizeof (unsigned)) | |||
1023 | return u (); | |||
1024 | else | |||
1025 | return wu (); | |||
1026 | } | |||
1027 | ||||
1028 | /* Buffer simply memcpied. */ | |||
1029 | void * | |||
1030 | bytes_out::buf (size_t len) | |||
1031 | { | |||
1032 | align (sizeof (void *) * 2); | |||
1033 | return write (len); | |||
1034 | } | |||
1035 | ||||
1036 | void | |||
1037 | bytes_out::buf (const void *src, size_t len) | |||
1038 | { | |||
1039 | if (void *ptr = buf (len)) | |||
1040 | memcpy (ptr, src, len); | |||
1041 | } | |||
1042 | ||||
1043 | const void * | |||
1044 | bytes_in::buf (size_t len) | |||
1045 | { | |||
1046 | align (sizeof (void *) * 2); | |||
1047 | const char *ptr = read (len); | |||
1048 | ||||
1049 | return ptr; | |||
1050 | } | |||
1051 | ||||
1052 | /* strings as an size_t length, followed by the buffer. Make sure | |||
1053 | there's a NUL terminator on read. */ | |||
1054 | ||||
1055 | void | |||
1056 | bytes_out::str (const char *string, size_t len) | |||
1057 | { | |||
1058 | z (len); | |||
1059 | if (len) | |||
1060 | { | |||
1061 | gcc_checking_assert (!string[len])((void)(!(!string[len]) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1061, __FUNCTION__), 0 : 0)); | |||
1062 | buf (string, len + 1); | |||
1063 | } | |||
1064 | } | |||
1065 | ||||
1066 | const char * | |||
1067 | bytes_in::str (size_t *len_p) | |||
1068 | { | |||
1069 | size_t len = z (); | |||
1070 | ||||
1071 | /* We're about to trust some user data. */ | |||
1072 | if (overrun) | |||
1073 | len = 0; | |||
1074 | if (len_p) | |||
1075 | *len_p = len; | |||
1076 | const char *str = NULLnullptr; | |||
1077 | if (len) | |||
1078 | { | |||
1079 | str = reinterpret_cast<const char *> (buf (len + 1)); | |||
1080 | if (!str || str[len]) | |||
1081 | { | |||
1082 | set_overrun (); | |||
1083 | str = NULLnullptr; | |||
1084 | } | |||
1085 | } | |||
1086 | return str ? str : ""; | |||
1087 | } | |||
1088 | ||||
1089 | cpp_hashnode * | |||
1090 | bytes_in::cpp_node () | |||
1091 | { | |||
1092 | size_t len; | |||
1093 | const char *s = str (&len); | |||
1094 | if (!len) | |||
1095 | return NULLnullptr; | |||
1096 | return ::cpp_node (get_identifier_with_length (s, len)); | |||
1097 | } | |||
1098 | ||||
1099 | /* Format a string directly to the buffer, including a terminating | |||
1100 | NUL. Intended for human consumption. */ | |||
1101 | ||||
1102 | void | |||
1103 | bytes_out::printf (const char *format, ...) | |||
1104 | { | |||
1105 | va_list args; | |||
1106 | /* Exercise buffer expansion. */ | |||
1107 | size_t len = EXPERIMENT (10, 500)((((2301211953U)) >= (1U << 20)) ? (10) : (500)); | |||
1108 | ||||
1109 | while (char *ptr = write (len)) | |||
1110 | { | |||
1111 | va_start (args, format)__builtin_va_start(args, format); | |||
1112 | size_t actual = vsnprintf (ptr, len, format, args) + 1; | |||
1113 | va_end (args)__builtin_va_end(args); | |||
1114 | if (actual <= len) | |||
1115 | { | |||
1116 | unuse (len - actual); | |||
1117 | break; | |||
1118 | } | |||
1119 | unuse (len); | |||
1120 | len = actual; | |||
1121 | } | |||
1122 | } | |||
1123 | ||||
1124 | void | |||
1125 | bytes_out::print_time (const char *kind, const tm *time, const char *tz) | |||
1126 | { | |||
1127 | printf ("%stime: %4u/%02u/%02u %02u:%02u:%02u %s", | |||
1128 | kind, time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, | |||
1129 | time->tm_hour, time->tm_min, time->tm_sec, tz); | |||
1130 | } | |||
1131 | ||||
1132 | /* Encapsulated Lazy Records Of Named Declarations. | |||
1133 | Header: Stunningly Elf32_Ehdr-like | |||
1134 | Sections: Sectional data | |||
1135 | [1-N) : User data sections | |||
1136 | N .strtab : strings, stunningly ELF STRTAB-like | |||
1137 | Index: Section table, stunningly ELF32_Shdr-like. */ | |||
1138 | ||||
1139 | class elf { | |||
1140 | protected: | |||
1141 | /* Constants used within the format. */ | |||
1142 | enum private_constants { | |||
1143 | /* File kind. */ | |||
1144 | ET_NONE = 0, | |||
1145 | EM_NONE = 0, | |||
1146 | OSABI_NONE = 0, | |||
1147 | ||||
1148 | /* File format. */ | |||
1149 | EV_CURRENT = 1, | |||
1150 | CLASS32 = 1, | |||
1151 | DATA2LSB = 1, | |||
1152 | DATA2MSB = 2, | |||
1153 | ||||
1154 | /* Section numbering. */ | |||
1155 | SHN_UNDEF = 0, | |||
1156 | SHN_LORESERVE = 0xff00, | |||
1157 | SHN_XINDEX = 0xffff, | |||
1158 | ||||
1159 | /* Section types. */ | |||
1160 | SHT_NONE = 0, /* No contents. */ | |||
1161 | SHT_PROGBITS = 1, /* Random bytes. */ | |||
1162 | SHT_STRTAB = 3, /* A string table. */ | |||
1163 | ||||
1164 | /* Section flags. */ | |||
1165 | SHF_NONE = 0x00, /* Nothing. */ | |||
1166 | SHF_STRINGS = 0x20, /* NUL-Terminated strings. */ | |||
1167 | ||||
1168 | /* I really hope we do not get CMI files larger than 4GB. */ | |||
1169 | MY_CLASS = CLASS32, | |||
1170 | /* It is host endianness that is relevant. */ | |||
1171 | MY_ENDIAN = DATA2LSB | |||
1172 | #ifdef WORDS_BIGENDIAN | |||
1173 | ^ DATA2LSB ^ DATA2MSB | |||
1174 | #endif | |||
1175 | }; | |||
1176 | ||||
1177 | public: | |||
1178 | /* Constants visible to users. */ | |||
1179 | enum public_constants { | |||
1180 | /* Special error codes. Breaking layering a bit. */ | |||
1181 | E_BAD_DATA = -1, /* Random unexpected data errors. */ | |||
1182 | E_BAD_LAZY = -2, /* Badly ordered laziness. */ | |||
1183 | E_BAD_IMPORT = -3 /* A nested import failed. */ | |||
1184 | }; | |||
1185 | ||||
1186 | protected: | |||
1187 | /* File identification. On-disk representation. */ | |||
1188 | struct ident { | |||
1189 | uint8_t magic[4]; /* 0x7f, 'E', 'L', 'F' */ | |||
1190 | uint8_t klass; /* 4:CLASS32 */ | |||
1191 | uint8_t data; /* 5:DATA2[LM]SB */ | |||
1192 | uint8_t version; /* 6:EV_CURRENT */ | |||
1193 | uint8_t osabi; /* 7:OSABI_NONE */ | |||
1194 | uint8_t abiver; /* 8: 0 */ | |||
1195 | uint8_t pad[7]; /* 9-15 */ | |||
1196 | }; | |||
1197 | /* File header. On-disk representation. */ | |||
1198 | struct header { | |||
1199 | struct ident ident; | |||
1200 | uint16_t type; /* ET_NONE */ | |||
1201 | uint16_t machine; /* EM_NONE */ | |||
1202 | uint32_t version; /* EV_CURRENT */ | |||
1203 | uint32_t entry; /* 0 */ | |||
1204 | uint32_t phoff; /* 0 */ | |||
1205 | uint32_t shoff; /* Section Header Offset in file */ | |||
1206 | uint32_t flags; | |||
1207 | uint16_t ehsize; /* ELROND Header SIZE -- sizeof (header) */ | |||
1208 | uint16_t phentsize; /* 0 */ | |||
1209 | uint16_t phnum; /* 0 */ | |||
1210 | uint16_t shentsize; /* Section Header SIZE -- sizeof (section) */ | |||
1211 | uint16_t shnum; /* Section Header NUM */ | |||
1212 | uint16_t shstrndx; /* Section Header STRing iNDeX */ | |||
1213 | }; | |||
1214 | /* File section. On-disk representation. */ | |||
1215 | struct section { | |||
1216 | uint32_t name; /* String table offset. */ | |||
1217 | uint32_t type; /* SHT_* */ | |||
1218 | uint32_t flags; /* SHF_* */ | |||
1219 | uint32_t addr; /* 0 */ | |||
1220 | uint32_t offset; /* OFFSET in file */ | |||
1221 | uint32_t size; /* SIZE of section */ | |||
1222 | uint32_t link; /* 0 */ | |||
1223 | uint32_t info; /* 0 */ | |||
1224 | uint32_t addralign; /* 0 */ | |||
1225 | uint32_t entsize; /* ENTry SIZE, usually 0 */ | |||
1226 | }; | |||
1227 | ||||
1228 | protected: | |||
1229 | data hdr; /* The header. */ | |||
1230 | data sectab; /* The section table. */ | |||
1231 | data strtab; /* String table. */ | |||
1232 | int fd; /* File descriptor we're reading or writing. */ | |||
1233 | int err; /* Sticky error code. */ | |||
1234 | ||||
1235 | public: | |||
1236 | /* Construct from STREAM. E is errno if STREAM NULL. */ | |||
1237 | elf (int fd, int e) | |||
1238 | :hdr (), sectab (), strtab (), fd (fd), err (fd >= 0 ? 0 : e) | |||
1239 | {} | |||
1240 | ~elf () | |||
1241 | { | |||
1242 | gcc_checking_assert (fd < 0 && !hdr.buffer((void)(!(fd < 0 && !hdr.buffer && !sectab .buffer && !strtab.buffer) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1243, __FUNCTION__), 0 : 0)) | |||
1243 | && !sectab.buffer && !strtab.buffer)((void)(!(fd < 0 && !hdr.buffer && !sectab .buffer && !strtab.buffer) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1243, __FUNCTION__), 0 : 0)); | |||
1244 | } | |||
1245 | ||||
1246 | public: | |||
1247 | /* Return the error, if we have an error. */ | |||
1248 | int get_error () const | |||
1249 | { | |||
1250 | return err; | |||
1251 | } | |||
1252 | /* Set the error, unless it's already been set. */ | |||
1253 | void set_error (int e = E_BAD_DATA) | |||
1254 | { | |||
1255 | if (!err) | |||
1256 | err = e; | |||
1257 | } | |||
1258 | /* Get an error string. */ | |||
1259 | const char *get_error (const char *) const; | |||
1260 | ||||
1261 | public: | |||
1262 | /* Begin reading/writing file. Return false on error. */ | |||
1263 | bool begin () const | |||
1264 | { | |||
1265 | return !get_error (); | |||
1266 | } | |||
1267 | /* Finish reading/writing file. Return false on error. */ | |||
1268 | bool end (); | |||
1269 | }; | |||
1270 | ||||
1271 | /* Return error string. */ | |||
1272 | ||||
1273 | const char * | |||
1274 | elf::get_error (const char *name) const | |||
1275 | { | |||
1276 | if (!name) | |||
1277 | return "Unknown CMI mapping"; | |||
1278 | ||||
1279 | switch (err) | |||
1280 | { | |||
1281 | case 0: | |||
1282 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1282, __FUNCTION__)); | |||
1283 | case E_BAD_DATA: | |||
1284 | return "Bad file data"; | |||
1285 | case E_BAD_IMPORT: | |||
1286 | return "Bad import dependency"; | |||
1287 | case E_BAD_LAZY: | |||
1288 | return "Bad lazy ordering"; | |||
1289 | default: | |||
1290 | return xstrerror (err); | |||
1291 | } | |||
1292 | } | |||
1293 | ||||
1294 | /* Finish file, return true if there's an error. */ | |||
1295 | ||||
1296 | bool | |||
1297 | elf::end () | |||
1298 | { | |||
1299 | /* Close the stream and free the section table. */ | |||
1300 | if (fd >= 0 && close (fd)) | |||
1301 | set_error (errno(*__errno_location ())); | |||
1302 | fd = -1; | |||
1303 | ||||
1304 | return !get_error (); | |||
1305 | } | |||
1306 | ||||
1307 | /* ELROND reader. */ | |||
1308 | ||||
1309 | class elf_in : public elf { | |||
1310 | typedef elf parent; | |||
1311 | ||||
1312 | private: | |||
1313 | /* For freezing & defrosting. */ | |||
1314 | #if !defined (HOST_LACKS_INODE_NUMBERS) | |||
1315 | dev_t device; | |||
1316 | ino_t inode; | |||
1317 | #endif | |||
1318 | ||||
1319 | public: | |||
1320 | elf_in (int fd, int e) | |||
1321 | :parent (fd, e) | |||
1322 | { | |||
1323 | } | |||
1324 | ~elf_in () | |||
1325 | { | |||
1326 | } | |||
1327 | ||||
1328 | public: | |||
1329 | bool is_frozen () const | |||
1330 | { | |||
1331 | return fd < 0 && hdr.pos; | |||
1332 | } | |||
1333 | bool is_freezable () const | |||
1334 | { | |||
1335 | return fd >= 0 && hdr.pos; | |||
1336 | } | |||
1337 | void freeze (); | |||
1338 | bool defrost (const char *); | |||
1339 | ||||
1340 | /* If BYTES is in the mmapped area, allocate a new buffer for it. */ | |||
1341 | void preserve (bytes_in &bytes ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
1342 | { | |||
1343 | #if MAPPED_READING1 | |||
1344 | if (hdr.buffer && bytes.buffer >= hdr.buffer | |||
1345 | && bytes.buffer < hdr.buffer + hdr.pos) | |||
1346 | { | |||
1347 | char *buf = bytes.buffer; | |||
1348 | bytes.buffer = data::simple_memory.grow (NULLnullptr, bytes.size); | |||
1349 | memcpy (bytes.buffer, buf, bytes.size); | |||
1350 | } | |||
1351 | #endif | |||
1352 | } | |||
1353 | /* If BYTES is not in SELF's mmapped area, free it. SELF might be | |||
1354 | NULL. */ | |||
1355 | static void release (elf_in *self ATTRIBUTE_UNUSED__attribute__ ((__unused__)), bytes_in &bytes) | |||
1356 | { | |||
1357 | #if MAPPED_READING1 | |||
1358 | if (!(self && self->hdr.buffer && bytes.buffer >= self->hdr.buffer | |||
1359 | && bytes.buffer < self->hdr.buffer + self->hdr.pos)) | |||
1360 | #endif | |||
1361 | data::simple_memory.shrink (bytes.buffer); | |||
1362 | bytes.buffer = NULLnullptr; | |||
1363 | bytes.size = 0; | |||
1364 | } | |||
1365 | ||||
1366 | public: | |||
1367 | static void grow (data &data, unsigned needed) | |||
1368 | { | |||
1369 | gcc_checking_assert (!data.buffer)((void)(!(!data.buffer) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1369, __FUNCTION__), 0 : 0)); | |||
1370 | #if !MAPPED_READING1 | |||
1371 | data.buffer = XNEWVEC (char, needed)((char *) xmalloc (sizeof (char) * (needed))); | |||
1372 | #endif | |||
1373 | data.size = needed; | |||
1374 | } | |||
1375 | static void shrink (data &data) | |||
1376 | { | |||
1377 | #if !MAPPED_READING1 | |||
1378 | XDELETEVEC (data.buffer)free ((void*) (data.buffer)); | |||
1379 | #endif | |||
1380 | data.buffer = NULLnullptr; | |||
1381 | data.size = 0; | |||
1382 | } | |||
1383 | ||||
1384 | public: | |||
1385 | const section *get_section (unsigned s) const | |||
1386 | { | |||
1387 | if (s * sizeof (section) < sectab.size) | |||
1388 | return reinterpret_cast<const section *> | |||
1389 | (§ab.buffer[s * sizeof (section)]); | |||
1390 | else | |||
1391 | return NULLnullptr; | |||
1392 | } | |||
1393 | unsigned get_section_limit () const | |||
1394 | { | |||
1395 | return sectab.size / sizeof (section); | |||
1396 | } | |||
1397 | ||||
1398 | protected: | |||
1399 | const char *read (data *, unsigned, unsigned); | |||
1400 | ||||
1401 | public: | |||
1402 | /* Read section by number. */ | |||
1403 | bool read (data *d, const section *s) | |||
1404 | { | |||
1405 | return s && read (d, s->offset, s->size); | |||
1406 | } | |||
1407 | ||||
1408 | /* Find section by name. */ | |||
1409 | unsigned find (const char *name); | |||
1410 | /* Find section by index. */ | |||
1411 | const section *find (unsigned snum, unsigned type = SHT_PROGBITS); | |||
1412 | ||||
1413 | public: | |||
1414 | /* Release the string table, when we're done with it. */ | |||
1415 | void release () | |||
1416 | { | |||
1417 | shrink (strtab); | |||
1418 | } | |||
1419 | ||||
1420 | public: | |||
1421 | bool begin (location_t); | |||
1422 | bool end () | |||
1423 | { | |||
1424 | release (); | |||
1425 | #if MAPPED_READING1 | |||
1426 | if (hdr.buffer) | |||
1427 | munmap (hdr.buffer, hdr.pos); | |||
1428 | hdr.buffer = NULLnullptr; | |||
1429 | #endif | |||
1430 | shrink (sectab); | |||
1431 | ||||
1432 | return parent::end (); | |||
1433 | } | |||
1434 | ||||
1435 | public: | |||
1436 | /* Return string name at OFFSET. Checks OFFSET range. Always | |||
1437 | returns non-NULL. We know offset 0 is an empty string. */ | |||
1438 | const char *name (unsigned offset) | |||
1439 | { | |||
1440 | return &strtab.buffer[offset < strtab.size ? offset : 0]; | |||
1441 | } | |||
1442 | }; | |||
1443 | ||||
1444 | /* ELROND writer. */ | |||
1445 | ||||
1446 | class elf_out : public elf, public data::allocator { | |||
1447 | typedef elf parent; | |||
1448 | /* Desired section alignment on disk. */ | |||
1449 | static const int SECTION_ALIGN = 16; | |||
1450 | ||||
1451 | private: | |||
1452 | ptr_int_hash_map identtab; /* Map of IDENTIFIERS to strtab offsets. */ | |||
1453 | unsigned pos; /* Write position in file. */ | |||
1454 | #if MAPPED_WRITING1 | |||
1455 | unsigned offset; /* Offset of the mapping. */ | |||
1456 | unsigned extent; /* Length of mapping. */ | |||
1457 | unsigned page_size; /* System page size. */ | |||
1458 | #endif | |||
1459 | ||||
1460 | public: | |||
1461 | elf_out (int fd, int e) | |||
1462 | :parent (fd, e), identtab (500), pos (0) | |||
1463 | { | |||
1464 | #if MAPPED_WRITING1 | |||
1465 | offset = extent = 0; | |||
1466 | page_size = sysconf (_SC_PAGE_SIZE_SC_PAGESIZE); | |||
1467 | if (page_size < SECTION_ALIGN) | |||
1468 | /* Something really strange. */ | |||
1469 | set_error (EINVAL22); | |||
1470 | #endif | |||
1471 | } | |||
1472 | ~elf_out () | |||
1473 | { | |||
1474 | data::simple_memory.shrink (hdr); | |||
1475 | data::simple_memory.shrink (sectab); | |||
1476 | data::simple_memory.shrink (strtab); | |||
1477 | } | |||
1478 | ||||
1479 | #if MAPPED_WRITING1 | |||
1480 | private: | |||
1481 | void create_mapping (unsigned ext, bool extending = true); | |||
1482 | void remove_mapping (); | |||
1483 | #endif | |||
1484 | ||||
1485 | protected: | |||
1486 | using allocator::grow; | |||
1487 | char *grow (char *, unsigned needed) final override; | |||
1488 | #if MAPPED_WRITING1 | |||
1489 | using allocator::shrink; | |||
1490 | void shrink (char *) final override; | |||
1491 | #endif | |||
1492 | ||||
1493 | public: | |||
1494 | unsigned get_section_limit () const | |||
1495 | { | |||
1496 | return sectab.pos / sizeof (section); | |||
1497 | } | |||
1498 | ||||
1499 | protected: | |||
1500 | unsigned add (unsigned type, unsigned name = 0, | |||
1501 | unsigned off = 0, unsigned size = 0, unsigned flags = SHF_NONE); | |||
1502 | unsigned write (const data &); | |||
1503 | #if MAPPED_WRITING1 | |||
1504 | unsigned write (const bytes_out &); | |||
1505 | #endif | |||
1506 | ||||
1507 | public: | |||
1508 | /* IDENTIFIER to strtab offset. */ | |||
1509 | unsigned name (tree ident); | |||
1510 | /* String literal to strtab offset. */ | |||
1511 | unsigned name (const char *n); | |||
1512 | /* Qualified name of DECL to strtab offset. */ | |||
1513 | unsigned qualified_name (tree decl, bool is_defn); | |||
1514 | ||||
1515 | private: | |||
1516 | unsigned strtab_write (const char *s, unsigned l); | |||
1517 | void strtab_write (tree decl, int); | |||
1518 | ||||
1519 | public: | |||
1520 | /* Add a section with contents or strings. */ | |||
1521 | unsigned add (const bytes_out &, bool string_p, unsigned name); | |||
1522 | ||||
1523 | public: | |||
1524 | /* Begin and end writing. */ | |||
1525 | bool begin (); | |||
1526 | bool end (); | |||
1527 | }; | |||
1528 | ||||
1529 | /* Begin reading section NAME (of type PROGBITS) from SOURCE. | |||
1530 | Data always checked for CRC. */ | |||
1531 | ||||
1532 | bool | |||
1533 | bytes_in::begin (location_t loc, elf_in *source, const char *name) | |||
1534 | { | |||
1535 | unsigned snum = source->find (name); | |||
1536 | ||||
1537 | return begin (loc, source, snum, name); | |||
1538 | } | |||
1539 | ||||
1540 | /* Begin reading section numbered SNUM with NAME (may be NULL). */ | |||
1541 | ||||
1542 | bool | |||
1543 | bytes_in::begin (location_t loc, elf_in *source, unsigned snum, const char *name) | |||
1544 | { | |||
1545 | if (!source->read (this, source->find (snum)) | |||
1546 | || !size || !check_crc ()) | |||
1547 | { | |||
1548 | source->set_error (elf::E_BAD_DATA); | |||
1549 | source->shrink (*this); | |||
1550 | if (name) | |||
1551 | error_at (loc, "section %qs is missing or corrupted", name); | |||
1552 | else | |||
1553 | error_at (loc, "section #%u is missing or corrupted", snum); | |||
1554 | return false; | |||
1555 | } | |||
1556 | pos = 4; | |||
1557 | return true; | |||
1558 | } | |||
1559 | ||||
1560 | /* Finish reading a section. */ | |||
1561 | ||||
1562 | bool | |||
1563 | bytes_in::end (elf_in *src) | |||
1564 | { | |||
1565 | if (more_p ()) | |||
1566 | set_overrun (); | |||
1567 | if (overrun) | |||
1568 | src->set_error (); | |||
1569 | ||||
1570 | src->shrink (*this); | |||
1571 | ||||
1572 | return !overrun; | |||
1573 | } | |||
1574 | ||||
1575 | /* Begin writing buffer. */ | |||
1576 | ||||
1577 | void | |||
1578 | bytes_out::begin (bool need_crc) | |||
1579 | { | |||
1580 | if (need_crc) | |||
1581 | pos = 4; | |||
1582 | memory->grow (*this, 0, false); | |||
1583 | } | |||
1584 | ||||
1585 | /* Finish writing buffer. Stream out to SINK as named section NAME. | |||
1586 | Return section number or 0 on failure. If CRC_PTR is true, crc | |||
1587 | the data. Otherwise it is a string section. */ | |||
1588 | ||||
1589 | unsigned | |||
1590 | bytes_out::end (elf_out *sink, unsigned name, unsigned *crc_ptr) | |||
1591 | { | |||
1592 | lengths[3] += pos; | |||
1593 | spans[3]++; | |||
1594 | ||||
1595 | set_crc (crc_ptr); | |||
1596 | unsigned sec_num = sink->add (*this, !crc_ptr, name); | |||
1597 | memory->shrink (*this); | |||
1598 | ||||
1599 | return sec_num; | |||
1600 | } | |||
1601 | ||||
1602 | /* Close and open the file, without destroying it. */ | |||
1603 | ||||
1604 | void | |||
1605 | elf_in::freeze () | |||
1606 | { | |||
1607 | gcc_checking_assert (!is_frozen ())((void)(!(!is_frozen ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1607, __FUNCTION__), 0 : 0)); | |||
1608 | #if MAPPED_READING1 | |||
1609 | if (munmap (hdr.buffer, hdr.pos) < 0) | |||
1610 | set_error (errno(*__errno_location ())); | |||
1611 | #endif | |||
1612 | if (close (fd) < 0) | |||
1613 | set_error (errno(*__errno_location ())); | |||
1614 | fd = -1; | |||
1615 | } | |||
1616 | ||||
1617 | bool | |||
1618 | elf_in::defrost (const char *name) | |||
1619 | { | |||
1620 | gcc_checking_assert (is_frozen ())((void)(!(is_frozen ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1620, __FUNCTION__), 0 : 0)); | |||
1621 | struct stat stat; | |||
1622 | ||||
1623 | fd = open (name, O_RDONLY00 | O_CLOEXEC02000000 | O_BINARY0); | |||
1624 | if (fd < 0 || fstat (fd, &stat) < 0) | |||
1625 | set_error (errno(*__errno_location ())); | |||
1626 | else | |||
1627 | { | |||
1628 | bool ok = hdr.pos == unsigned (stat.st_size); | |||
1629 | #ifndef HOST_LACKS_INODE_NUMBERS | |||
1630 | if (device != stat.st_dev | |||
1631 | || inode != stat.st_ino) | |||
1632 | ok = false; | |||
1633 | #endif | |||
1634 | if (!ok) | |||
1635 | set_error (EMFILE24); | |||
1636 | #if MAPPED_READING1 | |||
1637 | if (ok) | |||
1638 | { | |||
1639 | char *mapping = reinterpret_cast<char *> | |||
1640 | (mmap (NULLnullptr, hdr.pos, PROT_READ0x1, MAP_SHARED0x01, fd, 0)); | |||
1641 | if (mapping == MAP_FAILED((void *) -1)) | |||
1642 | fail: | |||
1643 | set_error (errno(*__errno_location ())); | |||
1644 | else | |||
1645 | { | |||
1646 | if (madvise (mapping, hdr.pos, MADV_RANDOM1)) | |||
1647 | goto fail; | |||
1648 | ||||
1649 | /* These buffers are never NULL in this case. */ | |||
1650 | strtab.buffer = mapping + strtab.pos; | |||
1651 | sectab.buffer = mapping + sectab.pos; | |||
1652 | hdr.buffer = mapping; | |||
1653 | } | |||
1654 | } | |||
1655 | #endif | |||
1656 | } | |||
1657 | ||||
1658 | return !get_error (); | |||
1659 | } | |||
1660 | ||||
1661 | /* Read at current position into BUFFER. Return true on success. */ | |||
1662 | ||||
1663 | const char * | |||
1664 | elf_in::read (data *data, unsigned pos, unsigned length) | |||
1665 | { | |||
1666 | #if MAPPED_READING1 | |||
1667 | if (pos + length > hdr.pos) | |||
1668 | { | |||
1669 | set_error (EINVAL22); | |||
1670 | return NULLnullptr; | |||
1671 | } | |||
1672 | #else | |||
1673 | if (pos != ~0u && lseek (fd, pos, SEEK_SET0) < 0) | |||
1674 | { | |||
1675 | set_error (errno(*__errno_location ())); | |||
1676 | return NULLnullptr; | |||
1677 | } | |||
1678 | #endif | |||
1679 | grow (*data, length); | |||
1680 | #if MAPPED_READING1 | |||
1681 | data->buffer = hdr.buffer + pos; | |||
1682 | #else | |||
1683 | if (::read (fd, data->buffer, data->size) != ssize_t (length)) | |||
1684 | { | |||
1685 | set_error (errno(*__errno_location ())); | |||
1686 | shrink (*data); | |||
1687 | return NULLnullptr; | |||
1688 | } | |||
1689 | #endif | |||
1690 | ||||
1691 | return data->buffer; | |||
1692 | } | |||
1693 | ||||
1694 | /* Read section SNUM of TYPE. Return section pointer or NULL on error. */ | |||
1695 | ||||
1696 | const elf::section * | |||
1697 | elf_in::find (unsigned snum, unsigned type) | |||
1698 | { | |||
1699 | const section *sec = get_section (snum); | |||
1700 | if (!snum || !sec || sec->type != type) | |||
1701 | return NULLnullptr; | |||
1702 | return sec; | |||
1703 | } | |||
1704 | ||||
1705 | /* Find a section NAME and TYPE. Return section number, or zero on | |||
1706 | failure. */ | |||
1707 | ||||
1708 | unsigned | |||
1709 | elf_in::find (const char *sname) | |||
1710 | { | |||
1711 | for (unsigned pos = sectab.size; pos -= sizeof (section); ) | |||
1712 | { | |||
1713 | const section *sec | |||
1714 | = reinterpret_cast<const section *> (§ab.buffer[pos]); | |||
1715 | ||||
1716 | if (0 == strcmp (sname, name (sec->name))) | |||
1717 | return pos / sizeof (section); | |||
1718 | } | |||
1719 | ||||
1720 | return 0; | |||
1721 | } | |||
1722 | ||||
1723 | /* Begin reading file. Verify header. Pull in section and string | |||
1724 | tables. Return true on success. */ | |||
1725 | ||||
1726 | bool | |||
1727 | elf_in::begin (location_t loc) | |||
1728 | { | |||
1729 | if (!parent::begin ()) | |||
1730 | return false; | |||
1731 | ||||
1732 | struct stat stat; | |||
1733 | unsigned size = 0; | |||
1734 | if (!fstat (fd, &stat)) | |||
1735 | { | |||
1736 | #if !defined (HOST_LACKS_INODE_NUMBERS) | |||
1737 | device = stat.st_dev; | |||
1738 | inode = stat.st_ino; | |||
1739 | #endif | |||
1740 | /* Never generate files > 4GB, check we've not been given one. */ | |||
1741 | if (stat.st_size == unsigned (stat.st_size)) | |||
1742 | size = unsigned (stat.st_size); | |||
1743 | } | |||
1744 | ||||
1745 | #if MAPPED_READING1 | |||
1746 | /* MAP_SHARED so that the file is backing store. If someone else | |||
1747 | concurrently writes it, they're wrong. */ | |||
1748 | void *mapping = mmap (NULLnullptr, size, PROT_READ0x1, MAP_SHARED0x01, fd, 0); | |||
1749 | if (mapping == MAP_FAILED((void *) -1)) | |||
1750 | { | |||
1751 | fail: | |||
1752 | set_error (errno(*__errno_location ())); | |||
1753 | return false; | |||
1754 | } | |||
1755 | /* We'll be hopping over this randomly. Some systems declare the | |||
1756 | first parm as char *, and other declare it as void *. */ | |||
1757 | if (madvise (reinterpret_cast <char *> (mapping), size, MADV_RANDOM1)) | |||
1758 | goto fail; | |||
1759 | ||||
1760 | hdr.buffer = (char *)mapping; | |||
1761 | #else | |||
1762 | read (&hdr, 0, sizeof (header)); | |||
1763 | #endif | |||
1764 | hdr.pos = size; /* Record size of the file. */ | |||
1765 | ||||
1766 | const header *h = reinterpret_cast<const header *> (hdr.buffer); | |||
1767 | if (!h) | |||
1768 | return false; | |||
1769 | ||||
1770 | if (h->ident.magic[0] != 0x7f | |||
1771 | || h->ident.magic[1] != 'E' | |||
1772 | || h->ident.magic[2] != 'L' | |||
1773 | || h->ident.magic[3] != 'F') | |||
1774 | { | |||
1775 | error_at (loc, "not Encapsulated Lazy Records of Named Declarations"); | |||
1776 | failed: | |||
1777 | shrink (hdr); | |||
1778 | return false; | |||
1779 | } | |||
1780 | ||||
1781 | /* We expect a particular format -- the ELF is not intended to be | |||
1782 | distributable. */ | |||
1783 | if (h->ident.klass != MY_CLASS | |||
1784 | || h->ident.data != MY_ENDIAN | |||
1785 | || h->ident.version != EV_CURRENT | |||
1786 | || h->type != ET_NONE | |||
1787 | || h->machine != EM_NONE | |||
1788 | || h->ident.osabi != OSABI_NONE) | |||
1789 | { | |||
1790 | error_at (loc, "unexpected encapsulation format or type"); | |||
1791 | goto failed; | |||
1792 | } | |||
1793 | ||||
1794 | int e = -1; | |||
1795 | if (!h->shoff || h->shentsize != sizeof (section)) | |||
1796 | { | |||
1797 | malformed: | |||
1798 | set_error (e); | |||
1799 | error_at (loc, "encapsulation is malformed"); | |||
1800 | goto failed; | |||
1801 | } | |||
1802 | ||||
1803 | unsigned strndx = h->shstrndx; | |||
1804 | unsigned shnum = h->shnum; | |||
1805 | if (shnum == SHN_XINDEX) | |||
1806 | { | |||
1807 | if (!read (§ab, h->shoff, sizeof (section))) | |||
1808 | { | |||
1809 | section_table_fail: | |||
1810 | e = errno(*__errno_location ()); | |||
1811 | goto malformed; | |||
1812 | } | |||
1813 | shnum = get_section (0)->size; | |||
1814 | /* Freeing does mean we'll re-read it in the case we're not | |||
1815 | mapping, but this is going to be rare. */ | |||
1816 | shrink (sectab); | |||
1817 | } | |||
1818 | ||||
1819 | if (!shnum) | |||
1820 | goto malformed; | |||
1821 | ||||
1822 | if (!read (§ab, h->shoff, shnum * sizeof (section))) | |||
1823 | goto section_table_fail; | |||
1824 | ||||
1825 | if (strndx == SHN_XINDEX) | |||
1826 | strndx = get_section (0)->link; | |||
1827 | ||||
1828 | if (!read (&strtab, find (strndx, SHT_STRTAB))) | |||
1829 | goto malformed; | |||
1830 | ||||
1831 | /* The string table should be at least one byte, with NUL chars | |||
1832 | at either end. */ | |||
1833 | if (!(strtab.size && !strtab.buffer[0] | |||
1834 | && !strtab.buffer[strtab.size - 1])) | |||
1835 | goto malformed; | |||
1836 | ||||
1837 | #if MAPPED_READING1 | |||
1838 | /* Record the offsets of the section and string tables. */ | |||
1839 | sectab.pos = h->shoff; | |||
1840 | strtab.pos = shnum * sizeof (section); | |||
1841 | #else | |||
1842 | shrink (hdr); | |||
1843 | #endif | |||
1844 | ||||
1845 | return true; | |||
1846 | } | |||
1847 | ||||
1848 | /* Create a new mapping. */ | |||
1849 | ||||
1850 | #if MAPPED_WRITING1 | |||
1851 | void | |||
1852 | elf_out::create_mapping (unsigned ext, bool extending) | |||
1853 | { | |||
1854 | #ifndef HAVE_POSIX_FALLOCATE1 | |||
1855 | #define posix_fallocate(fd,off,len) ftruncate (fd, off + len) | |||
1856 | #endif | |||
1857 | void *mapping = MAP_FAILED((void *) -1); | |||
1858 | if (extending && ext < 1024 * 1024) | |||
1859 | { | |||
1860 | if (!posix_fallocate (fd, offset, ext * 2)) | |||
1861 | mapping = mmap (NULLnullptr, ext * 2, PROT_READ0x1 | PROT_WRITE0x2, | |||
1862 | MAP_SHARED0x01, fd, offset); | |||
1863 | if (mapping != MAP_FAILED((void *) -1)) | |||
1864 | ext *= 2; | |||
1865 | } | |||
1866 | if (mapping == MAP_FAILED((void *) -1)) | |||
1867 | { | |||
1868 | if (!extending || !posix_fallocate (fd, offset, ext)) | |||
1869 | mapping = mmap (NULLnullptr, ext, PROT_READ0x1 | PROT_WRITE0x2, | |||
1870 | MAP_SHARED0x01, fd, offset); | |||
1871 | if (mapping == MAP_FAILED((void *) -1)) | |||
1872 | { | |||
1873 | set_error (errno(*__errno_location ())); | |||
1874 | mapping = NULLnullptr; | |||
1875 | ext = 0; | |||
1876 | } | |||
1877 | } | |||
1878 | #undef posix_fallocate | |||
1879 | hdr.buffer = (char *)mapping; | |||
1880 | extent = ext; | |||
1881 | } | |||
1882 | #endif | |||
1883 | ||||
1884 | /* Flush out the current mapping. */ | |||
1885 | ||||
1886 | #if MAPPED_WRITING1 | |||
1887 | void | |||
1888 | elf_out::remove_mapping () | |||
1889 | { | |||
1890 | if (hdr.buffer) | |||
1891 | { | |||
1892 | /* MS_ASYNC dtrt with the removed mapping, including a | |||
1893 | subsequent overlapping remap. */ | |||
1894 | if (msync (hdr.buffer, extent, MS_ASYNC1) | |||
1895 | || munmap (hdr.buffer, extent)) | |||
1896 | /* We're somewhat screwed at this point. */ | |||
1897 | set_error (errno(*__errno_location ())); | |||
1898 | } | |||
1899 | ||||
1900 | hdr.buffer = NULLnullptr; | |||
1901 | } | |||
1902 | #endif | |||
1903 | ||||
1904 | /* Grow a mapping of PTR to be NEEDED bytes long. This gets | |||
1905 | interesting if the new size grows the EXTENT. */ | |||
1906 | ||||
1907 | char * | |||
1908 | elf_out::grow (char *data, unsigned needed) | |||
1909 | { | |||
1910 | if (!data) | |||
1911 | { | |||
1912 | /* First allocation, check we're aligned. */ | |||
1913 | gcc_checking_assert (!(pos & (SECTION_ALIGN - 1)))((void)(!(!(pos & (SECTION_ALIGN - 1))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1913, __FUNCTION__), 0 : 0)); | |||
1914 | #if MAPPED_WRITING1 | |||
1915 | data = hdr.buffer + (pos - offset); | |||
1916 | #endif | |||
1917 | } | |||
1918 | ||||
1919 | #if MAPPED_WRITING1 | |||
1920 | unsigned off = data - hdr.buffer; | |||
1921 | if (off + needed > extent) | |||
1922 | { | |||
1923 | /* We need to grow the mapping. */ | |||
1924 | unsigned lwm = off & ~(page_size - 1); | |||
1925 | unsigned hwm = (off + needed + page_size - 1) & ~(page_size - 1); | |||
1926 | ||||
1927 | gcc_checking_assert (hwm > extent)((void)(!(hwm > extent) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1927, __FUNCTION__), 0 : 0)); | |||
1928 | ||||
1929 | remove_mapping (); | |||
1930 | ||||
1931 | offset += lwm; | |||
1932 | create_mapping (extent < hwm - lwm ? hwm - lwm : extent); | |||
1933 | ||||
1934 | data = hdr.buffer + (off - lwm); | |||
1935 | } | |||
1936 | #else | |||
1937 | data = allocator::grow (data, needed); | |||
1938 | #endif | |||
1939 | ||||
1940 | return data; | |||
1941 | } | |||
1942 | ||||
1943 | #if MAPPED_WRITING1 | |||
1944 | /* Shrinking is a NOP. */ | |||
1945 | void | |||
1946 | elf_out::shrink (char *) | |||
1947 | { | |||
1948 | } | |||
1949 | #endif | |||
1950 | ||||
1951 | /* Write S of length L to the strtab buffer. L must include the ending | |||
1952 | NUL, if that's what you want. */ | |||
1953 | ||||
1954 | unsigned | |||
1955 | elf_out::strtab_write (const char *s, unsigned l) | |||
1956 | { | |||
1957 | if (strtab.pos + l > strtab.size) | |||
1958 | data::simple_memory.grow (strtab, strtab.pos + l, false); | |||
1959 | memcpy (strtab.buffer + strtab.pos, s, l); | |||
1960 | unsigned res = strtab.pos; | |||
1961 | strtab.pos += l; | |||
1962 | return res; | |||
1963 | } | |||
1964 | ||||
1965 | /* Write qualified name of decl. INNER >0 if this is a definition, <0 | |||
1966 | if this is a qualifier of an outer name. */ | |||
1967 | ||||
1968 | void | |||
1969 | elf_out::strtab_write (tree decl, int inner) | |||
1970 | { | |||
1971 | tree ctx = CP_DECL_CONTEXT (decl)(!(! (((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1971, __FUNCTION__))->decl_minimal.context)) || ((enum tree_code ) (((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1971, __FUNCTION__))->decl_minimal.context))->base.code ) == TRANSLATION_UNIT_DECL) ? ((contains_struct_check ((decl) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1971, __FUNCTION__))->decl_minimal.context) : cp_global_trees [CPTI_GLOBAL]); | |||
1972 | if (TYPE_P (ctx)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (ctx)->base.code))] == tcc_type)) | |||
1973 | ctx = TYPE_NAME (ctx)((tree_class_check ((ctx), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1973, __FUNCTION__))->type_common.name); | |||
1974 | if (ctx != global_namespacecp_global_trees[CPTI_GLOBAL]) | |||
1975 | strtab_write (ctx, -1); | |||
1976 | ||||
1977 | tree name = DECL_NAME (decl)((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1977, __FUNCTION__))->decl_minimal.name); | |||
1978 | if (!name) | |||
1979 | name = DECL_ASSEMBLER_NAME_RAW (decl)((contains_struct_check ((decl), (TS_DECL_WITH_VIS), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1979, __FUNCTION__))->decl_with_vis.assembler_name); | |||
1980 | strtab_write (IDENTIFIER_POINTER (name)((const char *) (tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1980, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), IDENTIFIER_LENGTH (name)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1980, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len )); | |||
1981 | ||||
1982 | if (inner) | |||
1983 | strtab_write (&"::{}"[inner+1], 2); | |||
1984 | } | |||
1985 | ||||
1986 | /* Map IDENTIFIER IDENT to strtab offset. Inserts into strtab if not | |||
1987 | already there. */ | |||
1988 | ||||
1989 | unsigned | |||
1990 | elf_out::name (tree ident) | |||
1991 | { | |||
1992 | unsigned res = 0; | |||
1993 | if (ident) | |||
1994 | { | |||
1995 | bool existed; | |||
1996 | int *slot = &identtab.get_or_insert (ident, &existed); | |||
1997 | if (!existed) | |||
1998 | *slot = strtab_write (IDENTIFIER_POINTER (ident)((const char *) (tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1998, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
1999 | IDENTIFIER_LENGTH (ident)((tree_check ((ident), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 1999, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len ) + 1); | |||
2000 | res = *slot; | |||
2001 | } | |||
2002 | return res; | |||
2003 | } | |||
2004 | ||||
2005 | /* Map LITERAL to strtab offset. Does not detect duplicates and | |||
2006 | expects LITERAL to remain live until strtab is written out. */ | |||
2007 | ||||
2008 | unsigned | |||
2009 | elf_out::name (const char *literal) | |||
2010 | { | |||
2011 | return strtab_write (literal, strlen (literal) + 1); | |||
2012 | } | |||
2013 | ||||
2014 | /* Map a DECL's qualified name to strtab offset. Does not detect | |||
2015 | duplicates. */ | |||
2016 | ||||
2017 | unsigned | |||
2018 | elf_out::qualified_name (tree decl, bool is_defn) | |||
2019 | { | |||
2020 | gcc_checking_assert (DECL_P (decl) && decl != global_namespace)((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (decl)->base.code))] == tcc_declaration ) && decl != cp_global_trees[CPTI_GLOBAL]) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2020, __FUNCTION__), 0 : 0)); | |||
2021 | unsigned result = strtab.pos; | |||
2022 | ||||
2023 | strtab_write (decl, is_defn); | |||
2024 | strtab_write ("", 1); | |||
2025 | ||||
2026 | return result; | |||
2027 | } | |||
2028 | ||||
2029 | /* Add section to file. Return section number. TYPE & NAME identify | |||
2030 | the section. OFF and SIZE identify the file location of its | |||
2031 | data. FLAGS contains additional info. */ | |||
2032 | ||||
2033 | unsigned | |||
2034 | elf_out::add (unsigned type, unsigned name, unsigned off, unsigned size, | |||
2035 | unsigned flags) | |||
2036 | { | |||
2037 | gcc_checking_assert (!(off & (SECTION_ALIGN - 1)))((void)(!(!(off & (SECTION_ALIGN - 1))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2037, __FUNCTION__), 0 : 0)); | |||
2038 | if (sectab.pos + sizeof (section) > sectab.size) | |||
2039 | data::simple_memory.grow (sectab, sectab.pos + sizeof (section), false); | |||
2040 | section *sec = reinterpret_cast<section *> (sectab.buffer + sectab.pos); | |||
2041 | memset (sec, 0, sizeof (section)); | |||
2042 | sec->type = type; | |||
2043 | sec->flags = flags; | |||
2044 | sec->name = name; | |||
2045 | sec->offset = off; | |||
2046 | sec->size = size; | |||
2047 | if (flags & SHF_STRINGS) | |||
2048 | sec->entsize = 1; | |||
2049 | ||||
2050 | unsigned res = sectab.pos; | |||
2051 | sectab.pos += sizeof (section); | |||
2052 | return res / sizeof (section); | |||
2053 | } | |||
2054 | ||||
2055 | /* Pad to the next alignment boundary, then write BUFFER to disk. | |||
2056 | Return the position of the start of the write, or zero on failure. */ | |||
2057 | ||||
2058 | unsigned | |||
2059 | elf_out::write (const data &buffer) | |||
2060 | { | |||
2061 | #if MAPPED_WRITING1 | |||
2062 | /* HDR is always mapped. */ | |||
2063 | if (&buffer != &hdr) | |||
2064 | { | |||
2065 | bytes_out out (this); | |||
2066 | grow (out, buffer.pos, true); | |||
2067 | if (out.buffer) | |||
2068 | memcpy (out.buffer, buffer.buffer, buffer.pos); | |||
2069 | shrink (out); | |||
2070 | } | |||
2071 | else | |||
2072 | /* We should have been aligned during the first allocation. */ | |||
2073 | gcc_checking_assert (!(pos & (SECTION_ALIGN - 1)))((void)(!(!(pos & (SECTION_ALIGN - 1))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2073, __FUNCTION__), 0 : 0)); | |||
2074 | #else | |||
2075 | if (::write (fd, buffer.buffer, buffer.pos) != ssize_t (buffer.pos)) | |||
2076 | { | |||
2077 | set_error (errno(*__errno_location ())); | |||
2078 | return 0; | |||
2079 | } | |||
2080 | #endif | |||
2081 | unsigned res = pos; | |||
2082 | pos += buffer.pos; | |||
2083 | ||||
2084 | if (unsigned padding = -pos & (SECTION_ALIGN - 1)) | |||
2085 | { | |||
2086 | #if !MAPPED_WRITING1 | |||
2087 | /* Align the section on disk, should help the necessary copies. | |||
2088 | fseeking to extend is non-portable. */ | |||
2089 | static char zero[SECTION_ALIGN]; | |||
2090 | if (::write (fd, &zero, padding) != ssize_t (padding)) | |||
2091 | set_error (errno(*__errno_location ())); | |||
2092 | #endif | |||
2093 | pos += padding; | |||
2094 | } | |||
2095 | return res; | |||
2096 | } | |||
2097 | ||||
2098 | /* Write a streaming buffer. It must be using us as an allocator. */ | |||
2099 | ||||
2100 | #if MAPPED_WRITING1 | |||
2101 | unsigned | |||
2102 | elf_out::write (const bytes_out &buf) | |||
2103 | { | |||
2104 | gcc_checking_assert (buf.memory == this)((void)(!(buf.memory == this) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2104, __FUNCTION__), 0 : 0)); | |||
2105 | /* A directly mapped buffer. */ | |||
2106 | gcc_checking_assert (buf.buffer - hdr.buffer >= 0((void)(!(buf.buffer - hdr.buffer >= 0 && buf.buffer - hdr.buffer + buf.size <= extent) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2107, __FUNCTION__), 0 : 0)) | |||
2107 | && buf.buffer - hdr.buffer + buf.size <= extent)((void)(!(buf.buffer - hdr.buffer >= 0 && buf.buffer - hdr.buffer + buf.size <= extent) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2107, __FUNCTION__), 0 : 0)); | |||
2108 | unsigned res = pos; | |||
2109 | pos += buf.pos; | |||
2110 | ||||
2111 | /* Align up. We're not going to advance into the next page. */ | |||
2112 | pos += -pos & (SECTION_ALIGN - 1); | |||
2113 | ||||
2114 | return res; | |||
2115 | } | |||
2116 | #endif | |||
2117 | ||||
2118 | /* Write data and add section. STRING_P is true for a string | |||
2119 | section, false for PROGBITS. NAME identifies the section (0 is the | |||
2120 | empty name). DATA is the contents. Return section number or 0 on | |||
2121 | failure (0 is the undef section). */ | |||
2122 | ||||
2123 | unsigned | |||
2124 | elf_out::add (const bytes_out &data, bool string_p, unsigned name) | |||
2125 | { | |||
2126 | unsigned off = write (data); | |||
2127 | ||||
2128 | return add (string_p ? SHT_STRTAB : SHT_PROGBITS, name, | |||
2129 | off, data.pos, string_p ? SHF_STRINGS : SHF_NONE); | |||
2130 | } | |||
2131 | ||||
2132 | /* Begin writing the file. Initialize the section table and write an | |||
2133 | empty header. Return false on failure. */ | |||
2134 | ||||
2135 | bool | |||
2136 | elf_out::begin () | |||
2137 | { | |||
2138 | if (!parent::begin ()) | |||
2139 | return false; | |||
2140 | ||||
2141 | /* Let the allocators pick a default. */ | |||
2142 | data::simple_memory.grow (strtab, 0, false); | |||
2143 | data::simple_memory.grow (sectab, 0, false); | |||
2144 | ||||
2145 | /* The string table starts with an empty string. */ | |||
2146 | name (""); | |||
2147 | ||||
2148 | /* Create the UNDEF section. */ | |||
2149 | add (SHT_NONE); | |||
2150 | ||||
2151 | #if MAPPED_WRITING1 | |||
2152 | /* Start a mapping. */ | |||
2153 | create_mapping (EXPERIMENT (page_size,((((2301211953U)) >= (1U << 20)) ? (page_size) : ((32767 + page_size) & ~(page_size - 1))) | |||
2154 | (32767 + page_size) & ~(page_size - 1))((((2301211953U)) >= (1U << 20)) ? (page_size) : ((32767 + page_size) & ~(page_size - 1)))); | |||
2155 | if (!hdr.buffer) | |||
2156 | return false; | |||
2157 | #endif | |||
2158 | ||||
2159 | /* Write an empty header. */ | |||
2160 | grow (hdr, sizeof (header), true); | |||
2161 | header *h = reinterpret_cast<header *> (hdr.buffer); | |||
2162 | memset (h, 0, sizeof (header)); | |||
2163 | hdr.pos = hdr.size; | |||
2164 | write (hdr); | |||
2165 | return !get_error (); | |||
2166 | } | |||
2167 | ||||
2168 | /* Finish writing the file. Write out the string & section tables. | |||
2169 | Fill in the header. Return true on error. */ | |||
2170 | ||||
2171 | bool | |||
2172 | elf_out::end () | |||
2173 | { | |||
2174 | if (fd >= 0) | |||
2175 | { | |||
2176 | /* Write the string table. */ | |||
2177 | unsigned strnam = name (".strtab"); | |||
2178 | unsigned stroff = write (strtab); | |||
2179 | unsigned strndx = add (SHT_STRTAB, strnam, stroff, strtab.pos, | |||
2180 | SHF_STRINGS); | |||
2181 | ||||
2182 | /* Store escape values in section[0]. */ | |||
2183 | if (strndx >= SHN_LORESERVE) | |||
2184 | { | |||
2185 | reinterpret_cast<section *> (sectab.buffer)->link = strndx; | |||
2186 | strndx = SHN_XINDEX; | |||
2187 | } | |||
2188 | unsigned shnum = sectab.pos / sizeof (section); | |||
2189 | if (shnum >= SHN_LORESERVE) | |||
2190 | { | |||
2191 | reinterpret_cast<section *> (sectab.buffer)->size = shnum; | |||
2192 | shnum = SHN_XINDEX; | |||
2193 | } | |||
2194 | ||||
2195 | unsigned shoff = write (sectab); | |||
2196 | ||||
2197 | #if MAPPED_WRITING1 | |||
2198 | if (offset) | |||
2199 | { | |||
2200 | remove_mapping (); | |||
2201 | offset = 0; | |||
2202 | create_mapping ((sizeof (header) + page_size - 1) & ~(page_size - 1), | |||
2203 | false); | |||
2204 | } | |||
2205 | unsigned length = pos; | |||
2206 | #else | |||
2207 | if (lseek (fd, 0, SEEK_SET0) < 0) | |||
2208 | set_error (errno(*__errno_location ())); | |||
2209 | #endif | |||
2210 | /* Write header. */ | |||
2211 | if (!get_error ()) | |||
2212 | { | |||
2213 | /* Write the correct header now. */ | |||
2214 | header *h = reinterpret_cast<header *> (hdr.buffer); | |||
2215 | h->ident.magic[0] = 0x7f; | |||
2216 | h->ident.magic[1] = 'E'; /* Elrond */ | |||
2217 | h->ident.magic[2] = 'L'; /* is an */ | |||
2218 | h->ident.magic[3] = 'F'; /* elf. */ | |||
2219 | h->ident.klass = MY_CLASS; | |||
2220 | h->ident.data = MY_ENDIAN; | |||
2221 | h->ident.version = EV_CURRENT; | |||
2222 | h->ident.osabi = OSABI_NONE; | |||
2223 | h->type = ET_NONE; | |||
2224 | h->machine = EM_NONE; | |||
2225 | h->version = EV_CURRENT; | |||
2226 | h->shoff = shoff; | |||
2227 | h->ehsize = sizeof (header); | |||
2228 | h->shentsize = sizeof (section); | |||
2229 | h->shnum = shnum; | |||
2230 | h->shstrndx = strndx; | |||
2231 | ||||
2232 | pos = 0; | |||
2233 | write (hdr); | |||
2234 | } | |||
2235 | ||||
2236 | #if MAPPED_WRITING1 | |||
2237 | remove_mapping (); | |||
2238 | if (ftruncate (fd, length)) | |||
2239 | set_error (errno(*__errno_location ())); | |||
2240 | #endif | |||
2241 | } | |||
2242 | ||||
2243 | data::simple_memory.shrink (sectab); | |||
2244 | data::simple_memory.shrink (strtab); | |||
2245 | ||||
2246 | return parent::end (); | |||
2247 | } | |||
2248 | ||||
2249 | /********************************************************************/ | |||
2250 | ||||
2251 | /* A dependency set. This is used during stream out to determine the | |||
2252 | connectivity of the graph. Every namespace-scope declaration that | |||
2253 | needs writing has a depset. The depset is filled with the (depsets | |||
2254 | of) declarations within this module that it references. For a | |||
2255 | declaration that'll generally be named types. For definitions | |||
2256 | it'll also be declarations in the body. | |||
2257 | ||||
2258 | From that we can convert the graph to a DAG, via determining the | |||
2259 | Strongly Connected Clusters. Each cluster is streamed | |||
2260 | independently, and thus we achieve lazy loading. | |||
2261 | ||||
2262 | Other decls that get a depset are namespaces themselves and | |||
2263 | unnameable declarations. */ | |||
2264 | ||||
2265 | class depset { | |||
2266 | private: | |||
2267 | tree entity; /* Entity, or containing namespace. */ | |||
2268 | uintptr_t discriminator; /* Flags or identifier. */ | |||
2269 | ||||
2270 | public: | |||
2271 | /* The kinds of entity the depset could describe. The ordering is | |||
2272 | significant, see entity_kind_name. */ | |||
2273 | enum entity_kind | |||
2274 | { | |||
2275 | EK_DECL, /* A decl. */ | |||
2276 | EK_SPECIALIZATION, /* A specialization. */ | |||
2277 | EK_PARTIAL, /* A partial specialization. */ | |||
2278 | EK_USING, /* A using declaration (at namespace scope). */ | |||
2279 | EK_NAMESPACE, /* A namespace. */ | |||
2280 | EK_REDIRECT, /* Redirect to a template_decl. */ | |||
2281 | EK_EXPLICIT_HWM, | |||
2282 | EK_BINDING = EK_EXPLICIT_HWM, /* Implicitly encoded. */ | |||
2283 | EK_FOR_BINDING, /* A decl being inserted for a binding. */ | |||
2284 | EK_INNER_DECL, /* A decl defined outside of its imported | |||
2285 | context. */ | |||
2286 | EK_DIRECT_HWM = EK_PARTIAL + 1, | |||
2287 | ||||
2288 | EK_BITS = 3 /* Only need to encode below EK_EXPLICIT_HWM. */ | |||
2289 | }; | |||
2290 | ||||
2291 | private: | |||
2292 | /* Placement of bit fields in discriminator. */ | |||
2293 | enum disc_bits | |||
2294 | { | |||
2295 | DB_ZERO_BIT, /* Set to disambiguate identifier from flags */ | |||
2296 | DB_SPECIAL_BIT, /* First dep slot is special. */ | |||
2297 | DB_KIND_BIT, /* Kind of the entity. */ | |||
2298 | DB_KIND_BITS = EK_BITS, | |||
2299 | DB_DEFN_BIT = DB_KIND_BIT + DB_KIND_BITS, | |||
2300 | DB_IS_MEMBER_BIT, /* Is an out-of-class member. */ | |||
2301 | DB_IS_INTERNAL_BIT, /* It is an (erroneous) | |||
2302 | internal-linkage entity. */ | |||
2303 | DB_REFS_INTERNAL_BIT, /* Refers to an internal-linkage | |||
2304 | entity. */ | |||
2305 | DB_IMPORTED_BIT, /* An imported entity. */ | |||
2306 | DB_UNREACHED_BIT, /* A yet-to-be reached entity. */ | |||
2307 | DB_HIDDEN_BIT, /* A hidden binding. */ | |||
2308 | /* The following bits are not independent, but enumerating them is | |||
2309 | awkward. */ | |||
2310 | DB_ALIAS_TMPL_INST_BIT, /* An alias template instantiation. */ | |||
2311 | DB_ALIAS_SPEC_BIT, /* Specialization of an alias template | |||
2312 | (in both spec tables). */ | |||
2313 | DB_TYPE_SPEC_BIT, /* Specialization in the type table. | |||
2314 | */ | |||
2315 | DB_FRIEND_SPEC_BIT, /* An instantiated template friend. */ | |||
2316 | }; | |||
2317 | ||||
2318 | public: | |||
2319 | /* The first slot is special for EK_SPECIALIZATIONS it is a | |||
2320 | spec_entry pointer. It is not relevant for the SCC | |||
2321 | determination. */ | |||
2322 | vec<depset *> deps; /* Depsets we reference. */ | |||
2323 | ||||
2324 | public: | |||
2325 | unsigned cluster; /* Strongly connected cluster, later entity number */ | |||
2326 | unsigned section; /* Section written to. */ | |||
2327 | /* During SCC construction, section is lowlink, until the depset is | |||
2328 | removed from the stack. See Tarjan algorithm for details. */ | |||
2329 | ||||
2330 | private: | |||
2331 | /* Construction via factories. Destruction via hash traits. */ | |||
2332 | depset (tree entity); | |||
2333 | ~depset (); | |||
2334 | ||||
2335 | public: | |||
2336 | static depset *make_binding (tree, tree); | |||
2337 | static depset *make_entity (tree, entity_kind, bool = false); | |||
2338 | /* Late setting a binding name -- /then/ insert into hash! */ | |||
2339 | inline void set_binding_name (tree name) | |||
2340 | { | |||
2341 | gcc_checking_assert (!get_name ())((void)(!(!get_name ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2341, __FUNCTION__), 0 : 0)); | |||
2342 | discriminator = reinterpret_cast<uintptr_t> (name); | |||
2343 | } | |||
2344 | ||||
2345 | private: | |||
2346 | template<unsigned I> void set_flag_bit () | |||
2347 | { | |||
2348 | gcc_checking_assert (I < 2 || !is_binding ())((void)(!(I < 2 || !is_binding ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2348, __FUNCTION__), 0 : 0)); | |||
2349 | discriminator |= 1u << I; | |||
2350 | } | |||
2351 | template<unsigned I> void clear_flag_bit () | |||
2352 | { | |||
2353 | gcc_checking_assert (I < 2 || !is_binding ())((void)(!(I < 2 || !is_binding ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2353, __FUNCTION__), 0 : 0)); | |||
2354 | discriminator &= ~(1u << I); | |||
2355 | } | |||
2356 | template<unsigned I> bool get_flag_bit () const | |||
2357 | { | |||
2358 | gcc_checking_assert (I < 2 || !is_binding ())((void)(!(I < 2 || !is_binding ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2358, __FUNCTION__), 0 : 0)); | |||
2359 | return bool ((discriminator >> I) & 1); | |||
2360 | } | |||
2361 | ||||
2362 | public: | |||
2363 | bool is_binding () const | |||
2364 | { | |||
2365 | return !get_flag_bit<DB_ZERO_BIT> (); | |||
2366 | } | |||
2367 | entity_kind get_entity_kind () const | |||
2368 | { | |||
2369 | if (is_binding ()) | |||
2370 | return EK_BINDING; | |||
2371 | return entity_kind ((discriminator >> DB_KIND_BIT) & ((1u << EK_BITS) - 1)); | |||
2372 | } | |||
2373 | const char *entity_kind_name () const; | |||
2374 | ||||
2375 | public: | |||
2376 | bool has_defn () const | |||
2377 | { | |||
2378 | return get_flag_bit<DB_DEFN_BIT> (); | |||
2379 | } | |||
2380 | ||||
2381 | public: | |||
2382 | /* This class-member is defined here, but the class was imported. */ | |||
2383 | bool is_member () const | |||
2384 | { | |||
2385 | gcc_checking_assert (get_entity_kind () == EK_DECL)((void)(!(get_entity_kind () == EK_DECL) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2385, __FUNCTION__), 0 : 0)); | |||
2386 | return get_flag_bit<DB_IS_MEMBER_BIT> (); | |||
2387 | } | |||
2388 | public: | |||
2389 | bool is_internal () const | |||
2390 | { | |||
2391 | return get_flag_bit<DB_IS_INTERNAL_BIT> (); | |||
2392 | } | |||
2393 | bool refs_internal () const | |||
2394 | { | |||
2395 | return get_flag_bit<DB_REFS_INTERNAL_BIT> (); | |||
2396 | } | |||
2397 | bool is_import () const | |||
2398 | { | |||
2399 | return get_flag_bit<DB_IMPORTED_BIT> (); | |||
2400 | } | |||
2401 | bool is_unreached () const | |||
2402 | { | |||
2403 | return get_flag_bit<DB_UNREACHED_BIT> (); | |||
2404 | } | |||
2405 | bool is_alias_tmpl_inst () const | |||
2406 | { | |||
2407 | return get_flag_bit<DB_ALIAS_TMPL_INST_BIT> (); | |||
2408 | } | |||
2409 | bool is_alias () const | |||
2410 | { | |||
2411 | return get_flag_bit<DB_ALIAS_SPEC_BIT> (); | |||
2412 | } | |||
2413 | bool is_hidden () const | |||
2414 | { | |||
2415 | return get_flag_bit<DB_HIDDEN_BIT> (); | |||
2416 | } | |||
2417 | bool is_type_spec () const | |||
2418 | { | |||
2419 | return get_flag_bit<DB_TYPE_SPEC_BIT> (); | |||
2420 | } | |||
2421 | bool is_friend_spec () const | |||
2422 | { | |||
2423 | return get_flag_bit<DB_FRIEND_SPEC_BIT> (); | |||
2424 | } | |||
2425 | ||||
2426 | public: | |||
2427 | /* We set these bit outside of depset. */ | |||
2428 | void set_hidden_binding () | |||
2429 | { | |||
2430 | set_flag_bit<DB_HIDDEN_BIT> (); | |||
2431 | } | |||
2432 | void clear_hidden_binding () | |||
2433 | { | |||
2434 | clear_flag_bit<DB_HIDDEN_BIT> (); | |||
2435 | } | |||
2436 | ||||
2437 | public: | |||
2438 | bool is_special () const | |||
2439 | { | |||
2440 | return get_flag_bit<DB_SPECIAL_BIT> (); | |||
2441 | } | |||
2442 | void set_special () | |||
2443 | { | |||
2444 | set_flag_bit<DB_SPECIAL_BIT> (); | |||
2445 | } | |||
2446 | ||||
2447 | public: | |||
2448 | tree get_entity () const | |||
2449 | { | |||
2450 | return entity; | |||
2451 | } | |||
2452 | tree get_name () const | |||
2453 | { | |||
2454 | gcc_checking_assert (is_binding ())((void)(!(is_binding ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2454, __FUNCTION__), 0 : 0)); | |||
2455 | return reinterpret_cast <tree> (discriminator); | |||
2456 | } | |||
2457 | ||||
2458 | public: | |||
2459 | /* Traits for a hash table of pointers to bindings. */ | |||
2460 | struct traits { | |||
2461 | /* Each entry is a pointer to a depset. */ | |||
2462 | typedef depset *value_type; | |||
2463 | /* We lookup by container:maybe-identifier pair. */ | |||
2464 | typedef std::pair<tree,tree> compare_type; | |||
2465 | ||||
2466 | static const bool empty_zero_p = true; | |||
2467 | ||||
2468 | /* hash and equality for compare_type. */ | |||
2469 | inline static hashval_t hash (const compare_type &p) | |||
2470 | { | |||
2471 | hashval_t h = pointer_hash<tree_node>::hash (p.first); | |||
2472 | if (p.second) | |||
2473 | { | |||
2474 | hashval_t nh = IDENTIFIER_HASH_VALUE (p.second)((tree_check ((p.second), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2474, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.hash_value ); | |||
2475 | h = iterative_hash_hashval_t (h, nh); | |||
2476 | } | |||
2477 | return h; | |||
2478 | } | |||
2479 | inline static bool equal (const value_type b, const compare_type &p) | |||
2480 | { | |||
2481 | if (b->entity != p.first) | |||
2482 | return false; | |||
2483 | ||||
2484 | if (p.second) | |||
2485 | return b->discriminator == reinterpret_cast<uintptr_t> (p.second); | |||
2486 | else | |||
2487 | return !b->is_binding (); | |||
2488 | } | |||
2489 | ||||
2490 | /* (re)hasher for a binding itself. */ | |||
2491 | inline static hashval_t hash (const value_type b) | |||
2492 | { | |||
2493 | hashval_t h = pointer_hash<tree_node>::hash (b->entity); | |||
2494 | if (b->is_binding ()) | |||
2495 | { | |||
2496 | hashval_t nh = IDENTIFIER_HASH_VALUE (b->get_name ())((tree_check ((b->get_name ()), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2496, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.hash_value ); | |||
2497 | h = iterative_hash_hashval_t (h, nh); | |||
2498 | } | |||
2499 | return h; | |||
2500 | } | |||
2501 | ||||
2502 | /* Empty via NULL. */ | |||
2503 | static inline void mark_empty (value_type &p) {p = NULLnullptr;} | |||
2504 | static inline bool is_empty (value_type p) {return !p;} | |||
2505 | ||||
2506 | /* Nothing is deletable. Everything is insertable. */ | |||
2507 | static bool is_deleted (value_type) { return false; } | |||
2508 | static void mark_deleted (value_type) { gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2508, __FUNCTION__)); } | |||
2509 | ||||
2510 | /* We own the entities in the hash table. */ | |||
2511 | static void remove (value_type p) | |||
2512 | { | |||
2513 | delete (p); | |||
2514 | } | |||
2515 | }; | |||
2516 | ||||
2517 | public: | |||
2518 | class hash : public hash_table<traits> { | |||
2519 | typedef traits::compare_type key_t; | |||
2520 | typedef hash_table<traits> parent; | |||
2521 | ||||
2522 | public: | |||
2523 | vec<depset *> worklist; /* Worklist of decls to walk. */ | |||
2524 | hash *chain; /* Original table. */ | |||
2525 | depset *current; /* Current depset being depended. */ | |||
2526 | unsigned section; /* When writing out, the section. */ | |||
2527 | bool sneakoscope; /* Detecting dark magic (of a voldemort). */ | |||
2528 | bool reached_unreached; /* We reached an unreached entity. */ | |||
2529 | ||||
2530 | public: | |||
2531 | hash (size_t size, hash *c = NULLnullptr) | |||
2532 | : parent (size), chain (c), current (NULLnullptr), section (0), | |||
2533 | sneakoscope (false), reached_unreached (false) | |||
2534 | { | |||
2535 | worklist.create (size); | |||
2536 | } | |||
2537 | ~hash () | |||
2538 | { | |||
2539 | worklist.release (); | |||
2540 | } | |||
2541 | ||||
2542 | public: | |||
2543 | bool is_key_order () const | |||
2544 | { | |||
2545 | return chain != NULLnullptr; | |||
2546 | } | |||
2547 | ||||
2548 | private: | |||
2549 | depset **entity_slot (tree entity, bool = true); | |||
2550 | depset **binding_slot (tree ctx, tree name, bool = true); | |||
2551 | depset *maybe_add_declaration (tree decl); | |||
2552 | ||||
2553 | public: | |||
2554 | depset *find_dependency (tree entity); | |||
2555 | depset *find_binding (tree ctx, tree name); | |||
2556 | depset *make_dependency (tree decl, entity_kind); | |||
2557 | void add_dependency (depset *); | |||
2558 | ||||
2559 | public: | |||
2560 | void add_mergeable (depset *); | |||
2561 | depset *add_dependency (tree decl, entity_kind); | |||
2562 | void add_namespace_context (depset *, tree ns); | |||
2563 | ||||
2564 | private: | |||
2565 | static bool add_binding_entity (tree, WMB_Flags, void *); | |||
2566 | ||||
2567 | public: | |||
2568 | bool add_namespace_entities (tree ns, bitmap partitions); | |||
2569 | void add_specializations (bool decl_p); | |||
2570 | void add_partial_entities (vec<tree, va_gc> *); | |||
2571 | void add_class_entities (vec<tree, va_gc> *); | |||
2572 | ||||
2573 | public: | |||
2574 | void find_dependencies (module_state *); | |||
2575 | bool finalize_dependencies (); | |||
2576 | vec<depset *> connect (); | |||
2577 | }; | |||
2578 | ||||
2579 | public: | |||
2580 | struct tarjan { | |||
2581 | vec<depset *> result; | |||
2582 | vec<depset *> stack; | |||
2583 | unsigned index; | |||
2584 | ||||
2585 | tarjan (unsigned size) | |||
2586 | : index (0) | |||
2587 | { | |||
2588 | result.create (size); | |||
2589 | stack.create (50); | |||
2590 | } | |||
2591 | ~tarjan () | |||
2592 | { | |||
2593 | gcc_assert (!stack.length ())((void)(!(!stack.length ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2593, __FUNCTION__), 0 : 0)); | |||
2594 | stack.release (); | |||
2595 | } | |||
2596 | ||||
2597 | public: | |||
2598 | void connect (depset *); | |||
2599 | }; | |||
2600 | }; | |||
2601 | ||||
2602 | inline | |||
2603 | depset::depset (tree entity) | |||
2604 | :entity (entity), discriminator (0), cluster (0), section (0) | |||
2605 | { | |||
2606 | deps.create (0); | |||
2607 | } | |||
2608 | ||||
2609 | inline | |||
2610 | depset::~depset () | |||
2611 | { | |||
2612 | deps.release (); | |||
2613 | } | |||
2614 | ||||
2615 | const char * | |||
2616 | depset::entity_kind_name () const | |||
2617 | { | |||
2618 | /* Same order as entity_kind. */ | |||
2619 | static const char *const names[] = | |||
2620 | {"decl", "specialization", "partial", "using", | |||
2621 | "namespace", "redirect", "binding"}; | |||
2622 | entity_kind kind = get_entity_kind (); | |||
2623 | gcc_checking_assert (kind < ARRAY_SIZE (names))((void)(!(kind < (sizeof (names) / sizeof ((names)[0]))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2623, __FUNCTION__), 0 : 0)); | |||
2624 | return names[kind]; | |||
2625 | } | |||
2626 | ||||
2627 | /* Create a depset for a namespace binding NS::NAME. */ | |||
2628 | ||||
2629 | depset *depset::make_binding (tree ns, tree name) | |||
2630 | { | |||
2631 | depset *binding = new depset (ns); | |||
2632 | ||||
2633 | binding->discriminator = reinterpret_cast <uintptr_t> (name); | |||
2634 | ||||
2635 | return binding; | |||
2636 | } | |||
2637 | ||||
2638 | depset *depset::make_entity (tree entity, entity_kind ek, bool is_defn) | |||
2639 | { | |||
2640 | depset *r = new depset (entity); | |||
2641 | ||||
2642 | r->discriminator = ((1 << DB_ZERO_BIT) | |||
2643 | | (ek << DB_KIND_BIT) | |||
2644 | | is_defn << DB_DEFN_BIT); | |||
2645 | ||||
2646 | return r; | |||
2647 | } | |||
2648 | ||||
2649 | class pending_key | |||
2650 | { | |||
2651 | public: | |||
2652 | tree ns; | |||
2653 | tree id; | |||
2654 | }; | |||
2655 | ||||
2656 | template<> | |||
2657 | struct default_hash_traits<pending_key> | |||
2658 | { | |||
2659 | using value_type = pending_key; | |||
2660 | ||||
2661 | static const bool empty_zero_p = false; | |||
2662 | static hashval_t hash (const value_type &k) | |||
2663 | { | |||
2664 | hashval_t h = IDENTIFIER_HASH_VALUE (k.id)((tree_check ((k.id), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2664, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.hash_value ); | |||
2665 | h = iterative_hash_hashval_t (DECL_UID (k.ns)((contains_struct_check ((k.ns), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2665, __FUNCTION__))->decl_minimal.uid), h); | |||
2666 | ||||
2667 | return h; | |||
2668 | } | |||
2669 | static bool equal (const value_type &k, const value_type &l) | |||
2670 | { | |||
2671 | return k.ns == l.ns && k.id == l.id; | |||
2672 | } | |||
2673 | static void mark_empty (value_type &k) | |||
2674 | { | |||
2675 | k.ns = k.id = NULL_TREE(tree) nullptr; | |||
2676 | } | |||
2677 | static void mark_deleted (value_type &k) | |||
2678 | { | |||
2679 | k.ns = NULL_TREE(tree) nullptr; | |||
2680 | gcc_checking_assert (k.id)((void)(!(k.id) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 2680, __FUNCTION__), 0 : 0)); | |||
2681 | } | |||
2682 | static bool is_empty (const value_type &k) | |||
2683 | { | |||
2684 | return k.ns == NULL_TREE(tree) nullptr && k.id == NULL_TREE(tree) nullptr; | |||
2685 | } | |||
2686 | static bool is_deleted (const value_type &k) | |||
2687 | { | |||
2688 | return k.ns == NULL_TREE(tree) nullptr && k.id != NULL_TREE(tree) nullptr; | |||
2689 | } | |||
2690 | static void remove (value_type &) | |||
2691 | { | |||
2692 | } | |||
2693 | }; | |||
2694 | ||||
2695 | typedef hash_map<pending_key, auto_vec<unsigned>> pending_map_t; | |||
2696 | ||||
2697 | /* Not-loaded entities that are keyed to a namespace-scope | |||
2698 | identifier. See module_state::write_pendings for details. */ | |||
2699 | pending_map_t *pending_table; | |||
2700 | ||||
2701 | /* Decls that need some post processing once a batch of lazy loads has | |||
2702 | completed. */ | |||
2703 | vec<tree, va_heap, vl_embed> *post_load_decls; | |||
2704 | ||||
2705 | /* Some entities are keyed to another entitity for ODR purposes. | |||
2706 | For example, at namespace scope, 'inline auto var = []{};', that | |||
2707 | lambda is keyed to 'var', and follows its ODRness. */ | |||
2708 | typedef hash_map<tree, auto_vec<tree>> keyed_map_t; | |||
2709 | static keyed_map_t *keyed_table; | |||
2710 | ||||
2711 | /********************************************************************/ | |||
2712 | /* Tree streaming. The tree streaming is very specific to the tree | |||
2713 | structures themselves. A tag indicates the kind of tree being | |||
2714 | streamed. -ve tags indicate backreferences to already-streamed | |||
2715 | trees. Backreferences are auto-numbered. */ | |||
2716 | ||||
2717 | /* Tree tags. */ | |||
2718 | enum tree_tag { | |||
2719 | tt_null, /* NULL_TREE. */ | |||
2720 | tt_fixed, /* Fixed vector index. */ | |||
2721 | ||||
2722 | tt_node, /* By-value node. */ | |||
2723 | tt_decl, /* By-value mergeable decl. */ | |||
2724 | tt_tpl_parm, /* Template parm. */ | |||
2725 | ||||
2726 | /* The ordering of the following 4 is relied upon in | |||
2727 | trees_out::tree_node. */ | |||
2728 | tt_id, /* Identifier node. */ | |||
2729 | tt_conv_id, /* Conversion operator name. */ | |||
2730 | tt_anon_id, /* Anonymous name. */ | |||
2731 | tt_lambda_id, /* Lambda name. */ | |||
2732 | ||||
2733 | tt_typedef_type, /* A (possibly implicit) typedefed type. */ | |||
2734 | tt_derived_type, /* A type derived from another type. */ | |||
2735 | tt_variant_type, /* A variant of another type. */ | |||
2736 | ||||
2737 | tt_tinfo_var, /* Typeinfo object. */ | |||
2738 | tt_tinfo_typedef, /* Typeinfo typedef. */ | |||
2739 | tt_ptrmem_type, /* Pointer to member type. */ | |||
2740 | tt_nttp_var, /* NTTP_OBJECT VAR_DECL. */ | |||
2741 | ||||
2742 | tt_parm, /* Function parameter or result. */ | |||
2743 | tt_enum_value, /* An enum value. */ | |||
2744 | tt_enum_decl, /* An enum decl. */ | |||
2745 | tt_data_member, /* Data member/using-decl. */ | |||
2746 | ||||
2747 | tt_binfo, /* A BINFO. */ | |||
2748 | tt_vtable, /* A vtable. */ | |||
2749 | tt_thunk, /* A thunk. */ | |||
2750 | tt_clone_ref, | |||
2751 | ||||
2752 | tt_entity, /* A extra-cluster entity. */ | |||
2753 | ||||
2754 | tt_template, /* The TEMPLATE_RESULT of a template. */ | |||
2755 | }; | |||
2756 | ||||
2757 | enum walk_kind { | |||
2758 | WK_none, /* No walk to do (a back- or fixed-ref happened). */ | |||
2759 | WK_normal, /* Normal walk (by-name if possible). */ | |||
2760 | ||||
2761 | WK_value, /* By-value walk. */ | |||
2762 | }; | |||
2763 | ||||
2764 | enum merge_kind | |||
2765 | { | |||
2766 | MK_unique, /* Known unique. */ | |||
2767 | MK_named, /* Found by CTX, NAME + maybe_arg types etc. */ | |||
2768 | MK_field, /* Found by CTX and index on TYPE_FIELDS */ | |||
2769 | MK_vtable, /* Found by CTX and index on TYPE_VTABLES */ | |||
2770 | MK_as_base, /* Found by CTX. */ | |||
2771 | ||||
2772 | MK_partial, | |||
2773 | ||||
2774 | MK_enum, /* Found by CTX, & 1stMemberNAME. */ | |||
2775 | MK_keyed, /* Found by key & index. */ | |||
2776 | ||||
2777 | MK_friend_spec, /* Like named, but has a tmpl & args too. */ | |||
2778 | MK_local_friend, /* Found by CTX, index. */ | |||
2779 | ||||
2780 | MK_indirect_lwm = MK_enum, | |||
2781 | ||||
2782 | /* Template specialization kinds below. These are all found via | |||
2783 | primary template and specialization args. */ | |||
2784 | MK_template_mask = 0x10, /* A template specialization. */ | |||
2785 | ||||
2786 | MK_tmpl_decl_mask = 0x4, /* In decl table. */ | |||
2787 | MK_tmpl_alias_mask = 0x2, /* Also in type table */ | |||
2788 | ||||
2789 | MK_tmpl_tmpl_mask = 0x1, /* We want TEMPLATE_DECL. */ | |||
2790 | ||||
2791 | MK_type_spec = MK_template_mask, | |||
2792 | MK_decl_spec = MK_template_mask | MK_tmpl_decl_mask, | |||
2793 | MK_alias_spec = MK_decl_spec | MK_tmpl_alias_mask, | |||
2794 | ||||
2795 | MK_hwm = 0x20 | |||
2796 | }; | |||
2797 | /* This is more than a debugging array. NULLs are used to determine | |||
2798 | an invalid merge_kind number. */ | |||
2799 | static char const *const merge_kind_name[MK_hwm] = | |||
2800 | { | |||
2801 | "unique", "named", "field", "vtable", /* 0...3 */ | |||
2802 | "asbase", "partial", "enum", "attached", /* 4...7 */ | |||
2803 | ||||
2804 | "friend spec", "local friend", NULLnullptr, NULLnullptr, /* 8...11 */ | |||
2805 | NULLnullptr, NULLnullptr, NULLnullptr, NULLnullptr, | |||
2806 | ||||
2807 | "type spec", "type tmpl spec", /* 16,17 type (template). */ | |||
2808 | NULLnullptr, NULLnullptr, | |||
2809 | ||||
2810 | "decl spec", "decl tmpl spec", /* 20,21 decl (template). */ | |||
2811 | "alias spec", "alias tmpl spec", /* 22,23 alias (template). */ | |||
2812 | NULLnullptr, NULLnullptr, NULLnullptr, NULLnullptr, | |||
2813 | NULLnullptr, NULLnullptr, NULLnullptr, NULLnullptr, | |||
2814 | }; | |||
2815 | ||||
2816 | /* Mergeable entity location data. */ | |||
2817 | struct merge_key { | |||
2818 | cp_ref_qualifier ref_q : 2; | |||
2819 | unsigned index; | |||
2820 | ||||
2821 | tree ret; /* Return type, if appropriate. */ | |||
2822 | tree args; /* Arg types, if appropriate. */ | |||
2823 | ||||
2824 | tree constraints; /* Constraints. */ | |||
2825 | ||||
2826 | merge_key () | |||
2827 | :ref_q (REF_QUAL_NONE), index (0), | |||
2828 | ret (NULL_TREE(tree) nullptr), args (NULL_TREE(tree) nullptr), | |||
2829 | constraints (NULL_TREE(tree) nullptr) | |||
2830 | { | |||
2831 | } | |||
2832 | }; | |||
2833 | ||||
2834 | /* Hashmap of merged duplicates. Usually decls, but can contain | |||
2835 | BINFOs. */ | |||
2836 | typedef hash_map<tree,uintptr_t, | |||
2837 | simple_hashmap_traits<nodel_ptr_hash<tree_node>,uintptr_t> > | |||
2838 | duplicate_hash_map; | |||
2839 | ||||
2840 | /* Tree stream reader. Note that reading a stream doesn't mark the | |||
2841 | read trees with TREE_VISITED. Thus it's quite safe to have | |||
2842 | multiple concurrent readers. Which is good, because lazy | |||
2843 | loading. */ | |||
2844 | class trees_in : public bytes_in { | |||
2845 | typedef bytes_in parent; | |||
2846 | ||||
2847 | private: | |||
2848 | module_state *state; /* Module being imported. */ | |||
2849 | vec<tree> back_refs; /* Back references. */ | |||
2850 | duplicate_hash_map *duplicates; /* Map from existings to duplicate. */ | |||
2851 | vec<tree> post_decls; /* Decls to post process. */ | |||
2852 | unsigned unused; /* Inhibit any interior TREE_USED | |||
2853 | marking. */ | |||
2854 | ||||
2855 | public: | |||
2856 | trees_in (module_state *); | |||
2857 | ~trees_in (); | |||
2858 | ||||
2859 | public: | |||
2860 | int insert (tree); | |||
2861 | tree back_ref (int); | |||
2862 | ||||
2863 | private: | |||
2864 | tree start (unsigned = 0); | |||
2865 | ||||
2866 | public: | |||
2867 | /* Needed for binfo writing */ | |||
2868 | bool core_bools (tree); | |||
2869 | ||||
2870 | private: | |||
2871 | /* Stream tree_core, lang_decl_specific and lang_type_specific | |||
2872 | bits. */ | |||
2873 | bool core_vals (tree); | |||
2874 | bool lang_type_bools (tree); | |||
2875 | bool lang_type_vals (tree); | |||
2876 | bool lang_decl_bools (tree); | |||
2877 | bool lang_decl_vals (tree); | |||
2878 | bool lang_vals (tree); | |||
2879 | bool tree_node_bools (tree); | |||
2880 | bool tree_node_vals (tree); | |||
2881 | tree tree_value (); | |||
2882 | tree decl_value (); | |||
2883 | tree tpl_parm_value (); | |||
2884 | ||||
2885 | private: | |||
2886 | tree chained_decls (); /* Follow DECL_CHAIN. */ | |||
2887 | vec<tree, va_heap> *vec_chained_decls (); | |||
2888 | vec<tree, va_gc> *tree_vec (); /* vec of tree. */ | |||
2889 | vec<tree_pair_s, va_gc> *tree_pair_vec (); /* vec of tree_pair. */ | |||
2890 | tree tree_list (bool has_purpose); | |||
2891 | ||||
2892 | public: | |||
2893 | /* Read a tree node. */ | |||
2894 | tree tree_node (bool is_use = false); | |||
2895 | ||||
2896 | private: | |||
2897 | bool install_entity (tree decl); | |||
2898 | tree tpl_parms (unsigned &tpl_levels); | |||
2899 | bool tpl_parms_fini (tree decl, unsigned tpl_levels); | |||
2900 | bool tpl_header (tree decl, unsigned *tpl_levels); | |||
2901 | int fn_parms_init (tree); | |||
2902 | void fn_parms_fini (int tag, tree fn, tree existing, bool has_defn); | |||
2903 | unsigned add_indirect_tpl_parms (tree); | |||
2904 | public: | |||
2905 | bool add_indirects (tree); | |||
2906 | ||||
2907 | public: | |||
2908 | /* Serialize various definitions. */ | |||
2909 | bool read_definition (tree decl); | |||
2910 | ||||
2911 | private: | |||
2912 | bool is_matching_decl (tree existing, tree decl, bool is_typedef); | |||
2913 | static bool install_implicit_member (tree decl); | |||
2914 | bool read_function_def (tree decl, tree maybe_template); | |||
2915 | bool read_var_def (tree decl, tree maybe_template); | |||
2916 | bool read_class_def (tree decl, tree maybe_template); | |||
2917 | bool read_enum_def (tree decl, tree maybe_template); | |||
2918 | ||||
2919 | public: | |||
2920 | tree decl_container (); | |||
2921 | tree key_mergeable (int tag, merge_kind, tree decl, tree inner, tree type, | |||
2922 | tree container, bool is_attached); | |||
2923 | unsigned binfo_mergeable (tree *); | |||
2924 | ||||
2925 | private: | |||
2926 | uintptr_t *find_duplicate (tree existing); | |||
2927 | void register_duplicate (tree decl, tree existing); | |||
2928 | /* Mark as an already diagnosed bad duplicate. */ | |||
2929 | void unmatched_duplicate (tree existing) | |||
2930 | { | |||
2931 | *find_duplicate (existing) |= 1; | |||
2932 | } | |||
2933 | ||||
2934 | public: | |||
2935 | bool is_duplicate (tree decl) | |||
2936 | { | |||
2937 | return find_duplicate (decl) != NULLnullptr; | |||
2938 | } | |||
2939 | tree maybe_duplicate (tree decl) | |||
2940 | { | |||
2941 | if (uintptr_t *dup = find_duplicate (decl)) | |||
2942 | return reinterpret_cast<tree> (*dup & ~uintptr_t (1)); | |||
2943 | return decl; | |||
2944 | } | |||
2945 | tree odr_duplicate (tree decl, bool has_defn); | |||
2946 | ||||
2947 | public: | |||
2948 | /* Return the next decl to postprocess, or NULL. */ | |||
2949 | tree post_process () | |||
2950 | { | |||
2951 | return post_decls.length () ? post_decls.pop () : NULL_TREE(tree) nullptr; | |||
2952 | } | |||
2953 | private: | |||
2954 | /* Register DECL for postprocessing. */ | |||
2955 | void post_process (tree decl) | |||
2956 | { | |||
2957 | post_decls.safe_push (decl); | |||
2958 | } | |||
2959 | ||||
2960 | private: | |||
2961 | void assert_definition (tree, bool installing); | |||
2962 | }; | |||
2963 | ||||
2964 | trees_in::trees_in (module_state *state) | |||
2965 | :parent (), state (state), unused (0) | |||
2966 | { | |||
2967 | duplicates = NULLnullptr; | |||
2968 | back_refs.create (500); | |||
2969 | post_decls.create (0); | |||
2970 | } | |||
2971 | ||||
2972 | trees_in::~trees_in () | |||
2973 | { | |||
2974 | delete (duplicates); | |||
2975 | back_refs.release (); | |||
2976 | post_decls.release (); | |||
2977 | } | |||
2978 | ||||
2979 | /* Tree stream writer. */ | |||
2980 | class trees_out : public bytes_out { | |||
2981 | typedef bytes_out parent; | |||
2982 | ||||
2983 | private: | |||
2984 | module_state *state; /* The module we are writing. */ | |||
2985 | ptr_int_hash_map tree_map; /* Trees to references */ | |||
2986 | depset::hash *dep_hash; /* Dependency table. */ | |||
2987 | int ref_num; /* Back reference number. */ | |||
2988 | unsigned section; | |||
2989 | #if CHECKING_P1 | |||
2990 | int importedness; /* Checker that imports not occurring | |||
2991 | inappropriately. +ve imports ok, | |||
2992 | -ve imports not ok. */ | |||
2993 | #endif | |||
2994 | ||||
2995 | public: | |||
2996 | trees_out (allocator *, module_state *, depset::hash &deps, unsigned sec = 0); | |||
2997 | ~trees_out (); | |||
2998 | ||||
2999 | private: | |||
3000 | void mark_trees (); | |||
3001 | void unmark_trees (); | |||
3002 | ||||
3003 | public: | |||
3004 | /* Hey, let's ignore the well known STL iterator idiom. */ | |||
3005 | void begin (); | |||
3006 | unsigned end (elf_out *sink, unsigned name, unsigned *crc_ptr); | |||
3007 | void end (); | |||
3008 | ||||
3009 | public: | |||
3010 | enum tags | |||
3011 | { | |||
3012 | tag_backref = -1, /* Upper bound on the backrefs. */ | |||
3013 | tag_value = 0, /* Write by value. */ | |||
3014 | tag_fixed /* Lower bound on the fixed trees. */ | |||
3015 | }; | |||
3016 | ||||
3017 | public: | |||
3018 | bool is_key_order () const | |||
3019 | { | |||
3020 | return dep_hash->is_key_order (); | |||
3021 | } | |||
3022 | ||||
3023 | public: | |||
3024 | int insert (tree, walk_kind = WK_normal); | |||
3025 | ||||
3026 | private: | |||
3027 | void start (tree, bool = false); | |||
3028 | ||||
3029 | private: | |||
3030 | walk_kind ref_node (tree); | |||
3031 | public: | |||
3032 | int get_tag (tree); | |||
3033 | void set_importing (int i ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
3034 | { | |||
3035 | #if CHECKING_P1 | |||
3036 | importedness = i; | |||
3037 | #endif | |||
3038 | } | |||
3039 | ||||
3040 | private: | |||
3041 | void core_bools (tree); | |||
3042 | void core_vals (tree); | |||
3043 | void lang_type_bools (tree); | |||
3044 | void lang_type_vals (tree); | |||
3045 | void lang_decl_bools (tree); | |||
3046 | void lang_decl_vals (tree); | |||
3047 | void lang_vals (tree); | |||
3048 | void tree_node_bools (tree); | |||
3049 | void tree_node_vals (tree); | |||
3050 | ||||
3051 | private: | |||
3052 | void chained_decls (tree); | |||
3053 | void vec_chained_decls (tree); | |||
3054 | void tree_vec (vec<tree, va_gc> *); | |||
3055 | void tree_pair_vec (vec<tree_pair_s, va_gc> *); | |||
3056 | void tree_list (tree, bool has_purpose); | |||
3057 | ||||
3058 | public: | |||
3059 | /* Mark a node for by-value walking. */ | |||
3060 | void mark_by_value (tree); | |||
3061 | ||||
3062 | public: | |||
3063 | void tree_node (tree); | |||
3064 | ||||
3065 | private: | |||
3066 | void install_entity (tree decl, depset *); | |||
3067 | void tpl_parms (tree parms, unsigned &tpl_levels); | |||
3068 | void tpl_parms_fini (tree decl, unsigned tpl_levels); | |||
3069 | void fn_parms_fini (tree) {} | |||
3070 | unsigned add_indirect_tpl_parms (tree); | |||
3071 | public: | |||
3072 | void add_indirects (tree); | |||
3073 | void fn_parms_init (tree); | |||
3074 | void tpl_header (tree decl, unsigned *tpl_levels); | |||
3075 | ||||
3076 | public: | |||
3077 | merge_kind get_merge_kind (tree decl, depset *maybe_dep); | |||
3078 | tree decl_container (tree decl); | |||
3079 | void key_mergeable (int tag, merge_kind, tree decl, tree inner, | |||
3080 | tree container, depset *maybe_dep); | |||
3081 | void binfo_mergeable (tree binfo); | |||
3082 | ||||
3083 | private: | |||
3084 | bool decl_node (tree, walk_kind ref); | |||
3085 | void type_node (tree); | |||
3086 | void tree_value (tree); | |||
3087 | void tpl_parm_value (tree); | |||
3088 | ||||
3089 | public: | |||
3090 | void decl_value (tree, depset *); | |||
3091 | ||||
3092 | public: | |||
3093 | /* Serialize various definitions. */ | |||
3094 | void write_definition (tree decl); | |||
3095 | void mark_declaration (tree decl, bool do_defn); | |||
3096 | ||||
3097 | private: | |||
3098 | void mark_function_def (tree decl); | |||
3099 | void mark_var_def (tree decl); | |||
3100 | void mark_class_def (tree decl); | |||
3101 | void mark_enum_def (tree decl); | |||
3102 | void mark_class_member (tree decl, bool do_defn = true); | |||
3103 | void mark_binfos (tree type); | |||
3104 | ||||
3105 | private: | |||
3106 | void write_var_def (tree decl); | |||
3107 | void write_function_def (tree decl); | |||
3108 | void write_class_def (tree decl); | |||
3109 | void write_enum_def (tree decl); | |||
3110 | ||||
3111 | private: | |||
3112 | static void assert_definition (tree); | |||
3113 | ||||
3114 | public: | |||
3115 | static void instrument (); | |||
3116 | ||||
3117 | private: | |||
3118 | /* Tree instrumentation. */ | |||
3119 | static unsigned tree_val_count; | |||
3120 | static unsigned decl_val_count; | |||
3121 | static unsigned back_ref_count; | |||
3122 | static unsigned null_count; | |||
3123 | }; | |||
3124 | ||||
3125 | /* Instrumentation counters. */ | |||
3126 | unsigned trees_out::tree_val_count; | |||
3127 | unsigned trees_out::decl_val_count; | |||
3128 | unsigned trees_out::back_ref_count; | |||
3129 | unsigned trees_out::null_count; | |||
3130 | ||||
3131 | trees_out::trees_out (allocator *mem, module_state *state, depset::hash &deps, | |||
3132 | unsigned section) | |||
3133 | :parent (mem), state (state), tree_map (500), | |||
3134 | dep_hash (&deps), ref_num (0), section (section) | |||
3135 | { | |||
3136 | #if CHECKING_P1 | |||
3137 | importedness = 0; | |||
3138 | #endif | |||
3139 | } | |||
3140 | ||||
3141 | trees_out::~trees_out () | |||
3142 | { | |||
3143 | } | |||
3144 | ||||
3145 | /********************************************************************/ | |||
3146 | /* Location. We're aware of the line-map concept and reproduce it | |||
3147 | here. Each imported module allocates a contiguous span of ordinary | |||
3148 | maps, and of macro maps. adhoc maps are serialized by contents, | |||
3149 | not pre-allocated. The scattered linemaps of a module are | |||
3150 | coalesced when writing. */ | |||
3151 | ||||
3152 | ||||
3153 | /* I use half-open [first,second) ranges. */ | |||
3154 | typedef std::pair<unsigned,unsigned> range_t; | |||
3155 | ||||
3156 | /* A range of locations. */ | |||
3157 | typedef std::pair<location_t,location_t> loc_range_t; | |||
3158 | ||||
3159 | /* Spans of the line maps that are occupied by this TU. I.e. not | |||
3160 | within imports. Only extended when in an interface unit. | |||
3161 | Interval zero corresponds to the forced header linemap(s). This | |||
3162 | is a singleton object. */ | |||
3163 | ||||
3164 | class loc_spans { | |||
3165 | public: | |||
3166 | /* An interval of line maps. The line maps here represent a contiguous | |||
3167 | non-imported range. */ | |||
3168 | struct span { | |||
3169 | loc_range_t ordinary; /* Ordinary map location range. */ | |||
3170 | loc_range_t macro; /* Macro map location range. */ | |||
3171 | int ordinary_delta; /* Add to ordinary loc to get serialized loc. */ | |||
3172 | int macro_delta; /* Likewise for macro loc. */ | |||
3173 | }; | |||
3174 | ||||
3175 | private: | |||
3176 | vec<span> *spans; | |||
3177 | ||||
3178 | public: | |||
3179 | loc_spans () | |||
3180 | /* Do not preallocate spans, as that causes | |||
3181 | --enable-detailed-mem-stats problems. */ | |||
3182 | : spans (nullptr) | |||
3183 | { | |||
3184 | } | |||
3185 | ~loc_spans () | |||
3186 | { | |||
3187 | delete spans; | |||
3188 | } | |||
3189 | ||||
3190 | public: | |||
3191 | span &operator[] (unsigned ix) | |||
3192 | { | |||
3193 | return (*spans)[ix]; | |||
3194 | } | |||
3195 | unsigned length () const | |||
3196 | { | |||
3197 | return spans->length (); | |||
3198 | } | |||
3199 | ||||
3200 | public: | |||
3201 | bool init_p () const | |||
3202 | { | |||
3203 | return spans != nullptr; | |||
3204 | } | |||
3205 | /* Initializer. */ | |||
3206 | void init (const line_maps *lmaps, const line_map_ordinary *map); | |||
3207 | ||||
3208 | /* Slightly skewed preprocessed files can cause us to miss an | |||
3209 | initialization in some places. Fallback initializer. */ | |||
3210 | void maybe_init () | |||
3211 | { | |||
3212 | if (!init_p ()) | |||
3213 | init (line_table, nullptr); | |||
3214 | } | |||
3215 | ||||
3216 | public: | |||
3217 | enum { | |||
3218 | SPAN_RESERVED = 0, /* Reserved (fixed) locations. */ | |||
3219 | SPAN_FIRST = 1, /* LWM of locations to stream */ | |||
3220 | SPAN_MAIN = 2 /* Main file and onwards. */ | |||
3221 | }; | |||
3222 | ||||
3223 | public: | |||
3224 | location_t main_start () const | |||
3225 | { | |||
3226 | return (*spans)[SPAN_MAIN].ordinary.first; | |||
3227 | } | |||
3228 | ||||
3229 | public: | |||
3230 | void open (location_t); | |||
3231 | void close (); | |||
3232 | ||||
3233 | public: | |||
3234 | /* Propagate imported linemaps to us, if needed. */ | |||
3235 | bool maybe_propagate (module_state *import, location_t loc); | |||
3236 | ||||
3237 | public: | |||
3238 | const span *ordinary (location_t); | |||
3239 | const span *macro (location_t); | |||
3240 | }; | |||
3241 | ||||
3242 | static loc_spans spans; | |||
3243 | ||||
3244 | /* Information about ordinary locations we stream out. */ | |||
3245 | struct ord_loc_info | |||
3246 | { | |||
3247 | const line_map_ordinary *src; // line map we're based on | |||
3248 | unsigned offset; // offset to this line | |||
3249 | unsigned span; // number of locs we span | |||
3250 | unsigned remap; // serialization | |||
3251 | ||||
3252 | static int compare (const void *a_, const void *b_) | |||
3253 | { | |||
3254 | auto *a = static_cast<const ord_loc_info *> (a_); | |||
3255 | auto *b = static_cast<const ord_loc_info *> (b_); | |||
3256 | ||||
3257 | if (a->src != b->src) | |||
3258 | return a->src < b->src ? -1 : +1; | |||
3259 | ||||
3260 | // Ensure no overlap | |||
3261 | gcc_checking_assert (a->offset + a->span <= b->offset((void)(!(a->offset + a->span <= b->offset || b-> offset + b->span <= a->offset) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3262, __FUNCTION__), 0 : 0)) | |||
3262 | || b->offset + b->span <= a->offset)((void)(!(a->offset + a->span <= b->offset || b-> offset + b->span <= a->offset) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3262, __FUNCTION__), 0 : 0)); | |||
3263 | ||||
3264 | gcc_checking_assert (a->offset != b->offset)((void)(!(a->offset != b->offset) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3264, __FUNCTION__), 0 : 0)); | |||
3265 | return a->offset < b->offset ? -1 : +1; | |||
3266 | } | |||
3267 | }; | |||
3268 | struct ord_loc_traits | |||
3269 | { | |||
3270 | typedef ord_loc_info value_type; | |||
3271 | typedef value_type compare_type; | |||
3272 | ||||
3273 | static const bool empty_zero_p = false; | |||
3274 | ||||
3275 | static hashval_t hash (const value_type &v) | |||
3276 | { | |||
3277 | auto h = pointer_hash<const line_map_ordinary>::hash (v.src); | |||
3278 | return iterative_hash_hashval_t (v.offset, h); | |||
3279 | } | |||
3280 | static bool equal (const value_type &v, const compare_type p) | |||
3281 | { | |||
3282 | return v.src == p.src && v.offset == p.offset; | |||
3283 | } | |||
3284 | ||||
3285 | static void mark_empty (value_type &v) | |||
3286 | { | |||
3287 | v.src = nullptr; | |||
3288 | } | |||
3289 | static bool is_empty (value_type &v) | |||
3290 | { | |||
3291 | return !v.src; | |||
3292 | } | |||
3293 | ||||
3294 | static bool is_deleted (value_type &) { return false; } | |||
3295 | static void mark_deleted (value_type &) { gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3295, __FUNCTION__)); } | |||
3296 | ||||
3297 | static void remove (value_type &) {} | |||
3298 | }; | |||
3299 | /* Table keyed by ord_loc_info, used for noting. */ | |||
3300 | static hash_table<ord_loc_traits> *ord_loc_table; | |||
3301 | /* Sorted vector, used for writing. */ | |||
3302 | static vec<ord_loc_info> *ord_loc_remap; | |||
3303 | ||||
3304 | /* Information about macro locations we stream out. */ | |||
3305 | struct macro_loc_info | |||
3306 | { | |||
3307 | const line_map_macro *src; // original expansion | |||
3308 | unsigned remap; // serialization | |||
3309 | ||||
3310 | static int compare (const void *a_, const void *b_) | |||
3311 | { | |||
3312 | auto *a = static_cast<const macro_loc_info *> (a_); | |||
3313 | auto *b = static_cast<const macro_loc_info *> (b_); | |||
3314 | ||||
3315 | gcc_checking_assert (MAP_START_LOCATION (a->src)((void)(!(MAP_START_LOCATION (a->src) != MAP_START_LOCATION (b->src)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3316, __FUNCTION__), 0 : 0)) | |||
3316 | != MAP_START_LOCATION (b->src))((void)(!(MAP_START_LOCATION (a->src) != MAP_START_LOCATION (b->src)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3316, __FUNCTION__), 0 : 0)); | |||
3317 | if (MAP_START_LOCATION (a->src) < MAP_START_LOCATION (b->src)) | |||
3318 | return -1; | |||
3319 | else | |||
3320 | return +1; | |||
3321 | } | |||
3322 | }; | |||
3323 | struct macro_loc_traits | |||
3324 | { | |||
3325 | typedef macro_loc_info value_type; | |||
3326 | typedef const line_map_macro *compare_type; | |||
3327 | ||||
3328 | static const bool empty_zero_p = false; | |||
3329 | ||||
3330 | static hashval_t hash (compare_type p) | |||
3331 | { | |||
3332 | return pointer_hash<const line_map_macro>::hash (p); | |||
3333 | } | |||
3334 | static hashval_t hash (const value_type &v) | |||
3335 | { | |||
3336 | return hash (v.src); | |||
3337 | } | |||
3338 | static bool equal (const value_type &v, const compare_type p) | |||
3339 | { | |||
3340 | return v.src == p; | |||
3341 | } | |||
3342 | ||||
3343 | static void mark_empty (value_type &v) | |||
3344 | { | |||
3345 | v.src = nullptr; | |||
3346 | } | |||
3347 | static bool is_empty (value_type &v) | |||
3348 | { | |||
3349 | return !v.src; | |||
3350 | } | |||
3351 | ||||
3352 | static bool is_deleted (value_type &) { return false; } | |||
3353 | static void mark_deleted (value_type &) { gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3353, __FUNCTION__)); } | |||
3354 | ||||
3355 | static void remove (value_type &) {} | |||
3356 | }; | |||
3357 | /* Table keyed by line_map_macro, used for noting. */ | |||
3358 | static hash_table<macro_loc_traits> *macro_loc_table; | |||
3359 | /* Sorted vector, used for writing. */ | |||
3360 | static vec<macro_loc_info> *macro_loc_remap; | |||
3361 | ||||
3362 | /* Indirection to allow bsearching imports by ordinary location. */ | |||
3363 | static vec<module_state *> *ool; | |||
3364 | ||||
3365 | /********************************************************************/ | |||
3366 | /* Data needed by a module during the process of loading. */ | |||
3367 | struct GTY(()) slurping { | |||
3368 | ||||
3369 | /* Remap import's module numbering to our numbering. Values are | |||
3370 | shifted by 1. Bit0 encodes if the import is direct. */ | |||
3371 | vec<unsigned, va_heap, vl_embed> * | |||
3372 | GTY((skip)) remap; /* Module owner remapping. */ | |||
3373 | ||||
3374 | elf_in *GTY((skip)) from; /* The elf loader. */ | |||
3375 | ||||
3376 | /* This map is only for header imports themselves -- the global | |||
3377 | headers bitmap hold it for the current TU. */ | |||
3378 | bitmap headers; /* Transitive set of direct imports, including | |||
3379 | self. Used for macro visibility and | |||
3380 | priority. */ | |||
3381 | ||||
3382 | /* These objects point into the mmapped area, unless we're not doing | |||
3383 | that, or we got frozen or closed. In those cases they point to | |||
3384 | buffers we own. */ | |||
3385 | bytes_in macro_defs; /* Macro definitions. */ | |||
3386 | bytes_in macro_tbl; /* Macro table. */ | |||
3387 | ||||
3388 | /* Location remapping. first->ordinary, second->macro. */ | |||
3389 | range_t GTY((skip)) loc_deltas; | |||
3390 | ||||
3391 | unsigned current; /* Section currently being loaded. */ | |||
3392 | unsigned remaining; /* Number of lazy sections yet to read. */ | |||
3393 | unsigned lru; /* An LRU counter. */ | |||
3394 | ||||
3395 | public: | |||
3396 | slurping (elf_in *); | |||
3397 | ~slurping (); | |||
3398 | ||||
3399 | public: | |||
3400 | /* Close the ELF file, if it's open. */ | |||
3401 | void close () | |||
3402 | { | |||
3403 | if (from) | |||
3404 | { | |||
3405 | from->end (); | |||
3406 | delete from; | |||
3407 | from = NULLnullptr; | |||
3408 | } | |||
3409 | } | |||
3410 | ||||
3411 | public: | |||
3412 | void release_macros (); | |||
3413 | ||||
3414 | public: | |||
3415 | void alloc_remap (unsigned size) | |||
3416 | { | |||
3417 | gcc_assert (!remap)((void)(!(!remap) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3417, __FUNCTION__), 0 : 0)); | |||
3418 | vec_safe_reserve (remap, size); | |||
3419 | for (unsigned ix = size; ix--;) | |||
3420 | remap->quick_push (0); | |||
3421 | } | |||
3422 | unsigned remap_module (unsigned owner) | |||
3423 | { | |||
3424 | if (owner < remap->length ()) | |||
3425 | return (*remap)[owner] >> 1; | |||
3426 | return 0; | |||
3427 | } | |||
3428 | ||||
3429 | public: | |||
3430 | /* GC allocation. But we must explicitly delete it. */ | |||
3431 | static void *operator new (size_t x) | |||
3432 | { | |||
3433 | return ggc_alloc_atomic (x); | |||
3434 | } | |||
3435 | static void operator delete (void *p) | |||
3436 | { | |||
3437 | ggc_free (p); | |||
3438 | } | |||
3439 | }; | |||
3440 | ||||
3441 | slurping::slurping (elf_in *from) | |||
3442 | : remap (NULLnullptr), from (from), | |||
3443 | headers (BITMAP_GGC_ALLOCbitmap_gc_alloc ()), macro_defs (), macro_tbl (), | |||
3444 | loc_deltas (0, 0), | |||
3445 | current (~0u), remaining (0), lru (0) | |||
3446 | { | |||
3447 | } | |||
3448 | ||||
3449 | slurping::~slurping () | |||
3450 | { | |||
3451 | vec_free (remap); | |||
3452 | remap = NULLnullptr; | |||
3453 | release_macros (); | |||
3454 | close (); | |||
3455 | } | |||
3456 | ||||
3457 | void slurping::release_macros () | |||
3458 | { | |||
3459 | if (macro_defs.size) | |||
3460 | elf_in::release (from, macro_defs); | |||
3461 | if (macro_tbl.size) | |||
3462 | elf_in::release (from, macro_tbl); | |||
3463 | } | |||
3464 | ||||
3465 | /* Flags for extensions that end up being streamed. */ | |||
3466 | ||||
3467 | enum streamed_extensions { | |||
3468 | SE_OPENMP = 1 << 0, | |||
3469 | SE_BITS = 1 | |||
3470 | }; | |||
3471 | ||||
3472 | /* Counter indices. */ | |||
3473 | enum module_state_counts | |||
3474 | { | |||
3475 | MSC_sec_lwm, | |||
3476 | MSC_sec_hwm, | |||
3477 | MSC_pendings, | |||
3478 | MSC_entities, | |||
3479 | MSC_namespaces, | |||
3480 | MSC_bindings, | |||
3481 | MSC_macros, | |||
3482 | MSC_inits, | |||
3483 | MSC_HWM | |||
3484 | }; | |||
3485 | ||||
3486 | /********************************************************************/ | |||
3487 | struct module_state_config; | |||
3488 | ||||
3489 | /* Increasing levels of loadedness. */ | |||
3490 | enum module_loadedness { | |||
3491 | ML_NONE, /* Not loaded. */ | |||
3492 | ML_CONFIG, /* Config loaed. */ | |||
3493 | ML_PREPROCESSOR, /* Preprocessor loaded. */ | |||
3494 | ML_LANGUAGE, /* Language loaded. */ | |||
3495 | }; | |||
3496 | ||||
3497 | /* Increasing levels of directness (toplevel) of import. */ | |||
3498 | enum module_directness { | |||
3499 | MD_NONE, /* Not direct. */ | |||
3500 | MD_PARTITION_DIRECT, /* Direct import of a partition. */ | |||
3501 | MD_DIRECT, /* Direct import. */ | |||
3502 | MD_PURVIEW_DIRECT, /* direct import in purview. */ | |||
3503 | }; | |||
3504 | ||||
3505 | /* State of a particular module. */ | |||
3506 | ||||
3507 | class GTY((chain_next ("%h.parent"), for_user)) module_state { | |||
3508 | public: | |||
3509 | /* We always import & export ourselves. */ | |||
3510 | bitmap imports; /* Transitive modules we're importing. */ | |||
3511 | bitmap exports; /* Subset of that, that we're exporting. */ | |||
3512 | ||||
3513 | module_state *parent; | |||
3514 | tree name; /* Name of the module. */ | |||
3515 | ||||
3516 | slurping *slurp; /* Data for loading. */ | |||
3517 | ||||
3518 | const char *flatname; /* Flatname of module. */ | |||
3519 | char *filename; /* CMI Filename */ | |||
3520 | ||||
3521 | /* Indices into the entity_ary. */ | |||
3522 | unsigned entity_lwm; | |||
3523 | unsigned entity_num; | |||
3524 | ||||
3525 | /* Location ranges for this module. adhoc-locs are decomposed, so | |||
3526 | don't have a range. */ | |||
3527 | loc_range_t GTY((skip)) ordinary_locs; | |||
3528 | loc_range_t GTY((skip)) macro_locs; // [lwm,num) | |||
3529 | ||||
3530 | /* LOC is first set too the importing location. When initially | |||
3531 | loaded it refers to a module loc whose parent is the importing | |||
3532 | location. */ | |||
3533 | location_t loc; /* Location referring to module itself. */ | |||
3534 | unsigned crc; /* CRC we saw reading it in. */ | |||
3535 | ||||
3536 | unsigned mod; /* Module owner number. */ | |||
3537 | unsigned remap; /* Remapping during writing. */ | |||
3538 | ||||
3539 | unsigned short subst; /* Mangle subst if !0. */ | |||
3540 | ||||
3541 | /* How loaded this module is. */ | |||
3542 | enum module_loadedness loadedness : 2; | |||
3543 | ||||
3544 | bool module_p : 1; /* /The/ module of this TU. */ | |||
3545 | bool header_p : 1; /* Is a header unit. */ | |||
3546 | bool interface_p : 1; /* An interface. */ | |||
3547 | bool partition_p : 1; /* A partition. */ | |||
3548 | ||||
3549 | /* How directly this module is imported. */ | |||
3550 | enum module_directness directness : 2; | |||
3551 | ||||
3552 | bool exported_p : 1; /* directness != MD_NONE && exported. */ | |||
3553 | bool cmi_noted_p : 1; /* We've told the user about the CMI, don't | |||
3554 | do it again */ | |||
3555 | bool active_init_p : 1; /* This module's global initializer needs | |||
3556 | calling. */ | |||
3557 | bool inform_cmi_p : 1; /* Inform of a read/write. */ | |||
3558 | bool visited_p : 1; /* A walk-once flag. */ | |||
3559 | /* Record extensions emitted or permitted. */ | |||
3560 | unsigned extensions : SE_BITS; | |||
3561 | /* 14 bits used, 2 bits remain */ | |||
3562 | ||||
3563 | public: | |||
3564 | module_state (tree name, module_state *, bool); | |||
3565 | ~module_state (); | |||
3566 | ||||
3567 | public: | |||
3568 | void release () | |||
3569 | { | |||
3570 | imports = exports = NULLnullptr; | |||
3571 | slurped (); | |||
3572 | } | |||
3573 | void slurped () | |||
3574 | { | |||
3575 | delete slurp; | |||
3576 | slurp = NULLnullptr; | |||
3577 | } | |||
3578 | elf_in *from () const | |||
3579 | { | |||
3580 | return slurp->from; | |||
3581 | } | |||
3582 | ||||
3583 | public: | |||
3584 | /* Kind of this module. */ | |||
3585 | bool is_module () const | |||
3586 | { | |||
3587 | return module_p; | |||
3588 | } | |||
3589 | bool is_header () const | |||
3590 | { | |||
3591 | return header_p; | |||
3592 | } | |||
3593 | bool is_interface () const | |||
3594 | { | |||
3595 | return interface_p; | |||
3596 | } | |||
3597 | bool is_partition () const | |||
3598 | { | |||
3599 | return partition_p; | |||
3600 | } | |||
3601 | ||||
3602 | /* How this module is used in the current TU. */ | |||
3603 | bool is_exported () const | |||
3604 | { | |||
3605 | return exported_p; | |||
3606 | } | |||
3607 | bool is_direct () const | |||
3608 | { | |||
3609 | return directness >= MD_DIRECT; | |||
3610 | } | |||
3611 | bool is_purview_direct () const | |||
3612 | { | |||
3613 | return directness == MD_PURVIEW_DIRECT; | |||
3614 | } | |||
3615 | bool is_partition_direct () const | |||
3616 | { | |||
3617 | return directness == MD_PARTITION_DIRECT; | |||
3618 | } | |||
3619 | ||||
3620 | public: | |||
3621 | /* Is this a real module? */ | |||
3622 | bool has_location () const | |||
3623 | { | |||
3624 | return loc != UNKNOWN_LOCATION((location_t) 0); | |||
3625 | } | |||
3626 | ||||
3627 | public: | |||
3628 | bool check_not_purview (location_t loc); | |||
3629 | ||||
3630 | public: | |||
3631 | void mangle (bool include_partition); | |||
3632 | ||||
3633 | public: | |||
3634 | void set_import (module_state const *, bool is_export); | |||
3635 | void announce (const char *) const; | |||
3636 | ||||
3637 | public: | |||
3638 | /* Read and write module. */ | |||
3639 | void write_begin (elf_out *to, cpp_reader *, | |||
3640 | module_state_config &, unsigned &crc); | |||
3641 | void write_end (elf_out *to, cpp_reader *, | |||
3642 | module_state_config &, unsigned &crc); | |||
3643 | bool read_initial (cpp_reader *); | |||
3644 | bool read_preprocessor (bool); | |||
3645 | bool read_language (bool); | |||
3646 | ||||
3647 | public: | |||
3648 | /* Read a section. */ | |||
3649 | bool load_section (unsigned snum, binding_slot *mslot); | |||
3650 | /* Lazily read a section. */ | |||
3651 | bool lazy_load (unsigned index, binding_slot *mslot); | |||
3652 | ||||
3653 | public: | |||
3654 | /* Juggle a limited number of file numbers. */ | |||
3655 | static void freeze_an_elf (); | |||
3656 | bool maybe_defrost (); | |||
3657 | ||||
3658 | public: | |||
3659 | void maybe_completed_reading (); | |||
3660 | bool check_read (bool outermost, bool ok); | |||
3661 | ||||
3662 | private: | |||
3663 | /* The README, for human consumption. */ | |||
3664 | void write_readme (elf_out *to, cpp_reader *, const char *dialect); | |||
3665 | void write_env (elf_out *to); | |||
3666 | ||||
3667 | private: | |||
3668 | /* Import tables. */ | |||
3669 | void write_imports (bytes_out &cfg, bool direct); | |||
3670 | unsigned read_imports (bytes_in &cfg, cpp_reader *, line_maps *maps); | |||
3671 | ||||
3672 | private: | |||
3673 | void write_imports (elf_out *to, unsigned *crc_ptr); | |||
3674 | bool read_imports (cpp_reader *, line_maps *); | |||
3675 | ||||
3676 | private: | |||
3677 | void write_partitions (elf_out *to, unsigned, unsigned *crc_ptr); | |||
3678 | bool read_partitions (unsigned); | |||
3679 | ||||
3680 | private: | |||
3681 | void write_config (elf_out *to, struct module_state_config &, unsigned crc); | |||
3682 | bool read_config (struct module_state_config &); | |||
3683 | static void write_counts (elf_out *to, unsigned [MSC_HWM], unsigned *crc_ptr); | |||
3684 | bool read_counts (unsigned *); | |||
3685 | ||||
3686 | public: | |||
3687 | void note_cmi_name (); | |||
3688 | ||||
3689 | private: | |||
3690 | static unsigned write_bindings (elf_out *to, vec<depset *> depsets, | |||
3691 | unsigned *crc_ptr); | |||
3692 | bool read_bindings (unsigned count, unsigned lwm, unsigned hwm); | |||
3693 | ||||
3694 | static void write_namespace (bytes_out &sec, depset *ns_dep); | |||
3695 | tree read_namespace (bytes_in &sec); | |||
3696 | ||||
3697 | void write_namespaces (elf_out *to, vec<depset *> spaces, | |||
3698 | unsigned, unsigned *crc_ptr); | |||
3699 | bool read_namespaces (unsigned); | |||
3700 | ||||
3701 | void intercluster_seed (trees_out &sec, unsigned index, depset *dep); | |||
3702 | unsigned write_cluster (elf_out *to, depset *depsets[], unsigned size, | |||
3703 | depset::hash &, unsigned *counts, unsigned *crc_ptr); | |||
3704 | bool read_cluster (unsigned snum); | |||
3705 | ||||
3706 | private: | |||
3707 | unsigned write_inits (elf_out *to, depset::hash &, unsigned *crc_ptr); | |||
3708 | bool read_inits (unsigned count); | |||
3709 | ||||
3710 | private: | |||
3711 | unsigned write_pendings (elf_out *to, vec<depset *> depsets, | |||
3712 | depset::hash &, unsigned *crc_ptr); | |||
3713 | bool read_pendings (unsigned count); | |||
3714 | ||||
3715 | private: | |||
3716 | void write_entities (elf_out *to, vec<depset *> depsets, | |||
3717 | unsigned count, unsigned *crc_ptr); | |||
3718 | bool read_entities (unsigned count, unsigned lwm, unsigned hwm); | |||
3719 | ||||
3720 | private: | |||
3721 | void write_init_maps (); | |||
3722 | range_t write_prepare_maps (module_state_config *, bool); | |||
3723 | bool read_prepare_maps (const module_state_config *); | |||
3724 | ||||
3725 | void write_ordinary_maps (elf_out *to, range_t &, | |||
3726 | bool, unsigned *crc_ptr); | |||
3727 | bool read_ordinary_maps (unsigned, unsigned); | |||
3728 | void write_macro_maps (elf_out *to, range_t &, unsigned *crc_ptr); | |||
3729 | bool read_macro_maps (unsigned); | |||
3730 | ||||
3731 | private: | |||
3732 | void write_define (bytes_out &, const cpp_macro *); | |||
3733 | cpp_macro *read_define (bytes_in &, cpp_reader *) const; | |||
3734 | vec<cpp_hashnode *> *prepare_macros (cpp_reader *); | |||
3735 | unsigned write_macros (elf_out *to, vec<cpp_hashnode *> *, unsigned *crc_ptr); | |||
3736 | bool read_macros (); | |||
3737 | void install_macros (); | |||
3738 | ||||
3739 | public: | |||
3740 | void import_macros (); | |||
3741 | ||||
3742 | public: | |||
3743 | static void undef_macro (cpp_reader *, location_t, cpp_hashnode *); | |||
3744 | static cpp_macro *deferred_macro (cpp_reader *, location_t, cpp_hashnode *); | |||
3745 | ||||
3746 | public: | |||
3747 | static bool note_location (location_t); | |||
3748 | static void write_location (bytes_out &, location_t); | |||
3749 | location_t read_location (bytes_in &) const; | |||
3750 | ||||
3751 | public: | |||
3752 | void set_flatname (); | |||
3753 | const char *get_flatname () const | |||
3754 | { | |||
3755 | return flatname; | |||
3756 | } | |||
3757 | location_t imported_from () const; | |||
3758 | ||||
3759 | public: | |||
3760 | void set_filename (const Cody::Packet &); | |||
3761 | bool do_import (cpp_reader *, bool outermost); | |||
3762 | }; | |||
3763 | ||||
3764 | /* Hash module state by name. This cannot be a member of | |||
3765 | module_state, because of GTY restrictions. We never delete from | |||
3766 | the hash table, but ggc_ptr_hash doesn't support that | |||
3767 | simplification. */ | |||
3768 | ||||
3769 | struct module_state_hash : ggc_ptr_hash<module_state> { | |||
3770 | typedef std::pair<tree,uintptr_t> compare_type; /* {name,parent} */ | |||
3771 | ||||
3772 | static inline hashval_t hash (const value_type m); | |||
3773 | static inline hashval_t hash (const compare_type &n); | |||
3774 | static inline bool equal (const value_type existing, | |||
3775 | const compare_type &candidate); | |||
3776 | }; | |||
3777 | ||||
3778 | module_state::module_state (tree name, module_state *parent, bool partition) | |||
3779 | : imports (BITMAP_GGC_ALLOCbitmap_gc_alloc ()), exports (BITMAP_GGC_ALLOCbitmap_gc_alloc ()), | |||
3780 | parent (parent), name (name), slurp (NULLnullptr), | |||
3781 | flatname (NULLnullptr), filename (NULLnullptr), | |||
3782 | entity_lwm (~0u >> 1), entity_num (0), | |||
3783 | ordinary_locs (0, 0), macro_locs (0, 0), | |||
3784 | loc (UNKNOWN_LOCATION((location_t) 0)), | |||
3785 | crc (0), mod (MODULE_UNKNOWN(~0U)), remap (0), subst (0) | |||
3786 | { | |||
3787 | loadedness = ML_NONE; | |||
3788 | ||||
3789 | module_p = header_p = interface_p = partition_p = false; | |||
3790 | ||||
3791 | directness = MD_NONE; | |||
3792 | exported_p = false; | |||
3793 | ||||
3794 | cmi_noted_p = false; | |||
3795 | active_init_p = false; | |||
3796 | ||||
3797 | partition_p = partition; | |||
3798 | ||||
3799 | inform_cmi_p = false; | |||
3800 | visited_p = false; | |||
3801 | ||||
3802 | extensions = 0; | |||
3803 | if (name && TREE_CODE (name)((enum tree_code) (name)->base.code) == STRING_CST) | |||
3804 | { | |||
3805 | header_p = true; | |||
3806 | ||||
3807 | const char *string = TREE_STRING_POINTER (name)((const char *)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3807, __FUNCTION__, (STRING_CST)))->string.str)); | |||
3808 | gcc_checking_assert (string[0] == '.'((void)(!(string[0] == '.' ? (((string[1]) == '/') || (((string [1]) == '\\') && (0))) : (((((string)[0]) == '/') || ( (((string)[0]) == '\\') && (0))) || ((string)[0] && ((string)[1] == ':') && (0)))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3810, __FUNCTION__), 0 : 0)) | |||
3809 | ? IS_DIR_SEPARATOR (string[1])((void)(!(string[0] == '.' ? (((string[1]) == '/') || (((string [1]) == '\\') && (0))) : (((((string)[0]) == '/') || ( (((string)[0]) == '\\') && (0))) || ((string)[0] && ((string)[1] == ':') && (0)))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3810, __FUNCTION__), 0 : 0)) | |||
3810 | : IS_ABSOLUTE_PATH (string))((void)(!(string[0] == '.' ? (((string[1]) == '/') || (((string [1]) == '\\') && (0))) : (((((string)[0]) == '/') || ( (((string)[0]) == '\\') && (0))) || ((string)[0] && ((string)[1] == ':') && (0)))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3810, __FUNCTION__), 0 : 0)); | |||
3811 | } | |||
3812 | ||||
3813 | gcc_checking_assert (!(parent && header_p))((void)(!(!(parent && header_p)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3813, __FUNCTION__), 0 : 0)); | |||
3814 | } | |||
3815 | ||||
3816 | module_state::~module_state () | |||
3817 | { | |||
3818 | release (); | |||
3819 | } | |||
3820 | ||||
3821 | /* Hash module state. */ | |||
3822 | static hashval_t | |||
3823 | module_name_hash (const_tree name) | |||
3824 | { | |||
3825 | if (TREE_CODE (name)((enum tree_code) (name)->base.code) == STRING_CST) | |||
3826 | return htab_hash_string (TREE_STRING_POINTER (name)((const char *)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3826, __FUNCTION__, (STRING_CST)))->string.str))); | |||
3827 | else | |||
3828 | return IDENTIFIER_HASH_VALUE (name)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3828, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.hash_value ); | |||
3829 | } | |||
3830 | ||||
3831 | hashval_t | |||
3832 | module_state_hash::hash (const value_type m) | |||
3833 | { | |||
3834 | hashval_t ph = pointer_hash<void>::hash | |||
3835 | (reinterpret_cast<void *> (reinterpret_cast<uintptr_t> (m->parent) | |||
3836 | | m->is_partition ())); | |||
3837 | hashval_t nh = module_name_hash (m->name); | |||
3838 | return iterative_hash_hashval_t (ph, nh); | |||
3839 | } | |||
3840 | ||||
3841 | /* Hash a name. */ | |||
3842 | hashval_t | |||
3843 | module_state_hash::hash (const compare_type &c) | |||
3844 | { | |||
3845 | hashval_t ph = pointer_hash<void>::hash (reinterpret_cast<void *> (c.second)); | |||
3846 | hashval_t nh = module_name_hash (c.first); | |||
3847 | ||||
3848 | return iterative_hash_hashval_t (ph, nh); | |||
3849 | } | |||
3850 | ||||
3851 | bool | |||
3852 | module_state_hash::equal (const value_type existing, | |||
3853 | const compare_type &candidate) | |||
3854 | { | |||
3855 | uintptr_t ep = (reinterpret_cast<uintptr_t> (existing->parent) | |||
3856 | | existing->is_partition ()); | |||
3857 | if (ep != candidate.second) | |||
3858 | return false; | |||
3859 | ||||
3860 | /* Identifier comparison is by pointer. If the string_csts happen | |||
3861 | to be the same object, then they're equal too. */ | |||
3862 | if (existing->name == candidate.first) | |||
3863 | return true; | |||
3864 | ||||
3865 | /* If neither are string csts, they can't be equal. */ | |||
3866 | if (TREE_CODE (candidate.first)((enum tree_code) (candidate.first)->base.code) != STRING_CST | |||
3867 | || TREE_CODE (existing->name)((enum tree_code) (existing->name)->base.code) != STRING_CST) | |||
3868 | return false; | |||
3869 | ||||
3870 | /* String equality. */ | |||
3871 | if (TREE_STRING_LENGTH (existing->name)((tree_check ((existing->name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3871, __FUNCTION__, (STRING_CST)))->string.length) | |||
3872 | == TREE_STRING_LENGTH (candidate.first)((tree_check ((candidate.first), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3872, __FUNCTION__, (STRING_CST)))->string.length) | |||
3873 | && !memcmp (TREE_STRING_POINTER (existing->name)((const char *)((tree_check ((existing->name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3873, __FUNCTION__, (STRING_CST)))->string.str)), | |||
3874 | TREE_STRING_POINTER (candidate.first)((const char *)((tree_check ((candidate.first), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3874, __FUNCTION__, (STRING_CST)))->string.str)), | |||
3875 | TREE_STRING_LENGTH (existing->name)((tree_check ((existing->name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3875, __FUNCTION__, (STRING_CST)))->string.length))) | |||
3876 | return true; | |||
3877 | ||||
3878 | return false; | |||
3879 | } | |||
3880 | ||||
3881 | /********************************************************************/ | |||
3882 | /* Global state */ | |||
3883 | ||||
3884 | /* Mapper name. */ | |||
3885 | static const char *module_mapper_name; | |||
3886 | ||||
3887 | /* Deferred import queue (FIFO). */ | |||
3888 | static vec<module_state *, va_heap, vl_embed> *pending_imports; | |||
3889 | ||||
3890 | /* CMI repository path and workspace. */ | |||
3891 | static char *cmi_repo; | |||
3892 | static size_t cmi_repo_length; | |||
3893 | static char *cmi_path; | |||
3894 | static size_t cmi_path_alloc; | |||
3895 | ||||
3896 | /* Count of available and loaded clusters. */ | |||
3897 | static unsigned available_clusters; | |||
3898 | static unsigned loaded_clusters; | |||
3899 | ||||
3900 | /* What the current TU is. */ | |||
3901 | unsigned module_kind; | |||
3902 | ||||
3903 | /* Global trees. */ | |||
3904 | static const std::pair<tree *, unsigned> global_tree_arys[] = | |||
3905 | { | |||
3906 | std::pair<tree *, unsigned> (sizetype_tab, stk_type_kind_last), | |||
3907 | std::pair<tree *, unsigned> (integer_types, itk_none), | |||
3908 | std::pair<tree *, unsigned> (global_trees, TI_MODULE_HWM), | |||
3909 | std::pair<tree *, unsigned> (c_global_trees, CTI_MODULE_HWM), | |||
3910 | std::pair<tree *, unsigned> (cp_global_trees, CPTI_MODULE_HWM), | |||
3911 | std::pair<tree *, unsigned> (NULLnullptr, 0) | |||
3912 | }; | |||
3913 | static GTY(()) vec<tree, va_gc> *fixed_trees; | |||
3914 | static unsigned global_crc; | |||
3915 | ||||
3916 | /* Lazy loading can open many files concurrently, there are | |||
3917 | per-process limits on that. We pay attention to the process limit, | |||
3918 | and attempt to increase it when we run out. Otherwise we use an | |||
3919 | LRU scheme to figure out who to flush. Note that if the import | |||
3920 | graph /depth/ exceeds lazy_limit, we'll exceed the limit. */ | |||
3921 | static unsigned lazy_lru; /* LRU counter. */ | |||
3922 | static unsigned lazy_open; /* Number of open modules */ | |||
3923 | static unsigned lazy_limit; /* Current limit of open modules. */ | |||
3924 | static unsigned lazy_hard_limit; /* Hard limit on open modules. */ | |||
3925 | /* Account for source, assembler and dump files & directory searches. | |||
3926 | We don't keep the source file's open, so we don't have to account | |||
3927 | for #include depth. I think dump files are opened and closed per | |||
3928 | pass, but ICBW. */ | |||
3929 | #define LAZY_HEADROOM15 15 /* File descriptor headroom. */ | |||
3930 | ||||
3931 | /* Vector of module state. Indexed by OWNER. Has at least 2 slots. */ | |||
3932 | static GTY(()) vec<module_state *, va_gc> *modules; | |||
3933 | ||||
3934 | /* Hash of module state, findable by {name, parent}. */ | |||
3935 | static GTY(()) hash_table<module_state_hash> *modules_hash; | |||
3936 | ||||
3937 | /* Map of imported entities. We map DECL_UID to index of entity | |||
3938 | vector. */ | |||
3939 | typedef hash_map<unsigned/*UID*/, unsigned/*index*/, | |||
3940 | simple_hashmap_traits<int_hash<unsigned,0>, unsigned> | |||
3941 | > entity_map_t; | |||
3942 | static entity_map_t *entity_map; | |||
3943 | /* Doesn't need GTYing, because any tree referenced here is also | |||
3944 | findable by, symbol table, specialization table, return type of | |||
3945 | reachable function. */ | |||
3946 | static vec<binding_slot, va_heap, vl_embed> *entity_ary; | |||
3947 | ||||
3948 | /* Members entities of imported classes that are defined in this TU. | |||
3949 | These are where the entity's context is not from the current TU. | |||
3950 | We need to emit the definition (but not the enclosing class). | |||
3951 | ||||
3952 | We could find these by walking ALL the imported classes that we | |||
3953 | could provide a member definition. But that's expensive, | |||
3954 | especially when you consider lazy implicit member declarations, | |||
3955 | which could be ANY imported class. */ | |||
3956 | static GTY(()) vec<tree, va_gc> *class_members; | |||
3957 | ||||
3958 | /* The same problem exists for class template partial | |||
3959 | specializations. Now that we have constraints, the invariant of | |||
3960 | expecting them in the instantiation table no longer holds. One of | |||
3961 | the constrained partial specializations will be there, but the | |||
3962 | others not so much. It's not even an unconstrained partial | |||
3963 | spacialization in the table :( so any partial template declaration | |||
3964 | is added to this list too. */ | |||
3965 | static GTY(()) vec<tree, va_gc> *partial_specializations; | |||
3966 | ||||
3967 | /********************************************************************/ | |||
3968 | ||||
3969 | /* Our module mapper (created lazily). */ | |||
3970 | module_client *mapper; | |||
3971 | ||||
3972 | static module_client *make_mapper (location_t loc); | |||
3973 | inline module_client *get_mapper (location_t loc) | |||
3974 | { | |||
3975 | auto *res = mapper; | |||
3976 | if (!res) | |||
3977 | res = make_mapper (loc); | |||
3978 | return res; | |||
3979 | } | |||
3980 | ||||
3981 | /********************************************************************/ | |||
3982 | static tree | |||
3983 | get_clone_target (tree decl) | |||
3984 | { | |||
3985 | tree target; | |||
3986 | ||||
3987 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == TEMPLATE_DECL) | |||
3988 | { | |||
3989 | tree res_orig = DECL_CLONED_FUNCTION (DECL_TEMPLATE_RESULT (decl))(((contains_struct_check (((tree_check ((((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((decl ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3989, __FUNCTION__, (TEMPLATE_DECL))))))))->result), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3989, __FUNCTION__, (FUNCTION_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3989, __FUNCTION__))->decl_common.lang_specific)->u.fn .u5.cloned_function); | |||
3990 | ||||
3991 | target = DECL_TI_TEMPLATE (res_orig)((struct tree_template_info*)(tree_check (((((contains_struct_check ((template_info_decl_check ((res_orig), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3991, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3991, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3991, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
3992 | } | |||
3993 | else | |||
3994 | target = DECL_CLONED_FUNCTION (decl)(((contains_struct_check (((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3994, __FUNCTION__, (FUNCTION_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3994, __FUNCTION__))->decl_common.lang_specific)->u.fn .u5.cloned_function); | |||
3995 | ||||
3996 | gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (target))((void)(!(((((contains_struct_check ((target), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3996, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_CTOR_IDENTIFIER]) || (((contains_struct_check ((target) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3996, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_DTOR_IDENTIFIER]))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 3996, __FUNCTION__), 0 : 0)); | |||
3997 | ||||
3998 | return target; | |||
3999 | } | |||
4000 | ||||
4001 | /* Like FOR_EACH_CLONE, but will walk cloned templates. */ | |||
4002 | #define FOR_EVERY_CLONE(CLONE, FN)if (!((((contains_struct_check ((FN), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_CTOR_IDENTIFIER]) || (((contains_struct_check ((FN), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_DTOR_IDENTIFIER]))); else for (CLONE = (((contains_struct_check (((contains_struct_check ((FN), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->common.chain)); CLONE && ( ((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name) && ((!( (tree_not_check2 (((tree_check ((((contains_struct_check ((CLONE ), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__, (IDENTIFIER_NODE)))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_2)) & ((tree_not_check2 (((tree_check ((((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__, (IDENTIFIER_NODE)))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_1)) && !((((contains_struct_check ((CLONE) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_CTOR_IDENTIFIER]) || (((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_DTOR_IDENTIFIER]))); CLONE = (((contains_struct_check ( ((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4002, __FUNCTION__))->common.chain))) \ | |||
4003 | if (!DECL_MAYBE_IN_CHARGE_CDTOR_P (FN)((((contains_struct_check ((FN), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4003, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_CTOR_IDENTIFIER]) || (((contains_struct_check ((FN), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4003, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_DTOR_IDENTIFIER]))); \ | |||
4004 | else \ | |||
4005 | for (CLONE = DECL_CHAIN (FN)(((contains_struct_check (((contains_struct_check ((FN), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4005, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4005, __FUNCTION__))->common.chain)); \ | |||
4006 | CLONE && DECL_CLONED_FUNCTION_P (CLONE)(((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__))->decl_minimal.name) && ((!( (tree_not_check2 (((tree_check ((((contains_struct_check ((CLONE ), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__))->decl_minimal.name)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__, (IDENTIFIER_NODE)))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_2)) & ((tree_not_check2 (((tree_check ((((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__))->decl_minimal.name)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__, (IDENTIFIER_NODE)))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__, (TREE_VEC), (SSA_NAME)))->base.u.bits .lang_flag_1)) && !((((contains_struct_check ((CLONE) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_CTOR_IDENTIFIER]) || (((contains_struct_check ((CLONE), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4006, __FUNCTION__))->decl_minimal.name) == cp_global_trees [CPTI_DTOR_IDENTIFIER]))); \ | |||
4007 | CLONE = DECL_CHAIN (CLONE)(((contains_struct_check (((contains_struct_check ((CLONE), ( TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4007, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4007, __FUNCTION__))->common.chain))) | |||
4008 | ||||
4009 | /* It'd be nice if USE_TEMPLATE was a field of template_info | |||
4010 | (a) it'd solve the enum case dealt with below, | |||
4011 | (b) both class templates and decl templates would store this in the | |||
4012 | same place | |||
4013 | (c) this function wouldn't need the by-ref arg, which is annoying. */ | |||
4014 | ||||
4015 | static tree | |||
4016 | node_template_info (tree decl, int &use) | |||
4017 | { | |||
4018 | tree ti = NULL_TREE(tree) nullptr; | |||
4019 | int use_tpl = -1; | |||
4020 | if (DECL_IMPLICIT_TYPEDEF_P (decl)(((enum tree_code) (decl)->base.code) == TYPE_DECL && ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4020, __FUNCTION__))->decl_common.lang_flag_2))) | |||
4021 | { | |||
4022 | tree type = TREE_TYPE (decl)((contains_struct_check ((decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4022, __FUNCTION__))->typed.type); | |||
4023 | ||||
4024 | ti = TYPE_TEMPLATE_INFO (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOUND_TEMPLATE_TEMPLATE_PARM || (((enum tree_code) (type)->base.code) == RECORD_TYPE || ((enum tree_code) (type)->base.code) == UNION_TYPE || ((enum tree_code) (type)->base.code) == QUAL_UNION_TYPE) ? ((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4024, __FUNCTION__))->type_non_common.lang_1) : (tree) nullptr ); | |||
4025 | if (ti) | |||
4026 | { | |||
4027 | if (TYPE_LANG_SPECIFIC (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4027, __FUNCTION__))->type_with_lang_specific.lang_specific )) | |||
4028 | use_tpl = CLASSTYPE_USE_TEMPLATE (type)((((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4028, __FUNCTION__))->type_with_lang_specific.lang_specific ))->use_template); | |||
4029 | else | |||
4030 | { | |||
4031 | /* An enum, where we don't explicitly encode use_tpl. | |||
4032 | If the containing context (a type or a function), is | |||
4033 | an ({im,ex}plicit) instantiation, then this is too. | |||
4034 | If it's a partial or explicit specialization, then | |||
4035 | this is not!. */ | |||
4036 | tree ctx = CP_DECL_CONTEXT (decl)(!(! (((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4036, __FUNCTION__))->decl_minimal.context)) || ((enum tree_code ) (((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4036, __FUNCTION__))->decl_minimal.context))->base.code ) == TRANSLATION_UNIT_DECL) ? ((contains_struct_check ((decl) , (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4036, __FUNCTION__))->decl_minimal.context) : cp_global_trees [CPTI_GLOBAL]); | |||
4037 | if (TYPE_P (ctx)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (ctx)->base.code))] == tcc_type)) | |||
4038 | ctx = TYPE_NAME (ctx)((tree_class_check ((ctx), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4038, __FUNCTION__))->type_common.name); | |||
4039 | node_template_info (ctx, use); | |||
4040 | use_tpl = use != 2 ? use : 0; | |||
4041 | } | |||
4042 | } | |||
4043 | } | |||
4044 | else if (DECL_LANG_SPECIFIC (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4044, __FUNCTION__))->decl_common.lang_specific) | |||
4045 | && (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == VAR_DECL | |||
4046 | || TREE_CODE (decl)((enum tree_code) (decl)->base.code) == TYPE_DECL | |||
4047 | || TREE_CODE (decl)((enum tree_code) (decl)->base.code) == FUNCTION_DECL | |||
4048 | || TREE_CODE (decl)((enum tree_code) (decl)->base.code) == FIELD_DECL | |||
4049 | || TREE_CODE (decl)((enum tree_code) (decl)->base.code) == CONCEPT_DECL | |||
4050 | || TREE_CODE (decl)((enum tree_code) (decl)->base.code) == TEMPLATE_DECL)) | |||
4051 | { | |||
4052 | use_tpl = DECL_USE_TEMPLATE (decl)(((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4052, __FUNCTION__))->decl_common.lang_specific)->u.base .use_template); | |||
4053 | ti = DECL_TEMPLATE_INFO (decl)(((contains_struct_check ((template_info_decl_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4053, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4053, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info); | |||
4054 | } | |||
4055 | ||||
4056 | use = use_tpl; | |||
4057 | return ti; | |||
4058 | } | |||
4059 | ||||
4060 | /* Find the index in entity_ary for an imported DECL. It should | |||
4061 | always be there, but bugs can cause it to be missing, and that can | |||
4062 | crash the crash reporting -- let's not do that! When streaming | |||
4063 | out we place entities from this module there too -- with negated | |||
4064 | indices. */ | |||
4065 | ||||
4066 | static unsigned | |||
4067 | import_entity_index (tree decl, bool null_ok = false) | |||
4068 | { | |||
4069 | if (unsigned *slot = entity_map->get (DECL_UID (decl)((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4069, __FUNCTION__))->decl_minimal.uid))) | |||
4070 | return *slot; | |||
4071 | ||||
4072 | gcc_checking_assert (null_ok)((void)(!(null_ok) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4072, __FUNCTION__), 0 : 0)); | |||
4073 | return ~(~0u >> 1); | |||
4074 | } | |||
4075 | ||||
4076 | /* Find the module for an imported entity at INDEX in the entity ary. | |||
4077 | There must be one. */ | |||
4078 | ||||
4079 | static module_state * | |||
4080 | import_entity_module (unsigned index) | |||
4081 | { | |||
4082 | if (index > ~(~0u >> 1)) | |||
4083 | /* This is an index for an exported entity. */ | |||
4084 | return (*modules)[0]; | |||
4085 | ||||
4086 | /* Do not include the current TU (not an off-by-one error). */ | |||
4087 | unsigned pos = 1; | |||
4088 | unsigned len = modules->length () - pos; | |||
4089 | while (len) | |||
4090 | { | |||
4091 | unsigned half = len / 2; | |||
4092 | module_state *probe = (*modules)[pos + half]; | |||
4093 | if (index < probe->entity_lwm) | |||
4094 | len = half; | |||
4095 | else if (index < probe->entity_lwm + probe->entity_num) | |||
4096 | return probe; | |||
4097 | else | |||
4098 | { | |||
4099 | pos += half + 1; | |||
4100 | len = len - (half + 1); | |||
4101 | } | |||
4102 | } | |||
4103 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4103, __FUNCTION__)); | |||
4104 | } | |||
4105 | ||||
4106 | ||||
4107 | /********************************************************************/ | |||
4108 | /* A dumping machinery. */ | |||
4109 | ||||
4110 | class dumper { | |||
4111 | public: | |||
4112 | enum { | |||
4113 | LOCATION = TDF_LINENO, /* -lineno:Source location streaming. */ | |||
4114 | DEPEND = TDF_GRAPH, /* -graph:Dependency graph construction. */ | |||
4115 | CLUSTER = TDF_BLOCKS, /* -blocks:Clusters. */ | |||
4116 | TREE = TDF_UID, /* -uid:Tree streaming. */ | |||
4117 | MERGE = TDF_ALIAS, /* -alias:Mergeable Entities. */ | |||
4118 | ELF = TDF_ASMNAME, /* -asmname:Elf data. */ | |||
4119 | MACRO = TDF_VOPS /* -vops:Macros. */ | |||
4120 | }; | |||
4121 | ||||
4122 | private: | |||
4123 | struct impl { | |||
4124 | typedef vec<module_state *, va_heap, vl_embed> stack_t; | |||
4125 | ||||
4126 | FILE *stream; /* Dump stream. */ | |||
4127 | unsigned indent; /* Local indentation. */ | |||
4128 | bool bol; /* Beginning of line. */ | |||
4129 | stack_t stack; /* Trailing array of module_state. */ | |||
4130 | ||||
4131 | bool nested_name (tree); /* Dump a name following DECL_CONTEXT. */ | |||
4132 | }; | |||
4133 | ||||
4134 | public: | |||
4135 | /* The dumper. */ | |||
4136 | impl *dumps; | |||
4137 | dump_flags_t flags; | |||
4138 | ||||
4139 | public: | |||
4140 | /* Push/pop module state dumping. */ | |||
4141 | unsigned push (module_state *); | |||
4142 | void pop (unsigned); | |||
4143 | ||||
4144 | public: | |||
4145 | /* Change local indentation. */ | |||
4146 | void indent () | |||
4147 | { | |||
4148 | if (dumps) | |||
4149 | dumps->indent++; | |||
4150 | } | |||
4151 | void outdent () | |||
4152 | { | |||
4153 | if (dumps) | |||
4154 | { | |||
4155 | gcc_checking_assert (dumps->indent)((void)(!(dumps->indent) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4155, __FUNCTION__), 0 : 0)); | |||
4156 | dumps->indent--; | |||
4157 | } | |||
4158 | } | |||
4159 | ||||
4160 | public: | |||
4161 | /* Is dump enabled?. */ | |||
4162 | bool operator () (int mask = 0) | |||
4163 | { | |||
4164 | if (!dumps || !dumps->stream) | |||
4165 | return false; | |||
4166 | if (mask && !(mask & flags)) | |||
4167 | return false; | |||
4168 | return true; | |||
4169 | } | |||
4170 | /* Dump some information. */ | |||
4171 | bool operator () (const char *, ...); | |||
4172 | }; | |||
4173 | ||||
4174 | /* The dumper. */ | |||
4175 | static dumper dump = {0, dump_flags_t (0)}; | |||
4176 | ||||
4177 | /* Push to dumping M. Return previous indentation level. */ | |||
4178 | ||||
4179 | unsigned | |||
4180 | dumper::push (module_state *m) | |||
4181 | { | |||
4182 | FILE *stream = NULLnullptr; | |||
4183 | if (!dumps || !dumps->stack.length ()) | |||
4184 | { | |||
4185 | stream = dump_begin (module_dump_id, &flags); | |||
4186 | if (!stream) | |||
4187 | return 0; | |||
4188 | } | |||
4189 | ||||
4190 | if (!dumps || !dumps->stack.space (1)) | |||
4191 | { | |||
4192 | /* Create or extend the dump implementor. */ | |||
4193 | unsigned current = dumps ? dumps->stack.length () : 0; | |||
4194 | unsigned count = current ? current * 2 : EXPERIMENT (1, 20)((((2301211953U)) >= (1U << 20)) ? (1) : (20)); | |||
4195 | size_t alloc = (offsetof (impl, stack)__builtin_offsetof(impl, stack) | |||
4196 | + impl::stack_t::embedded_size (count)); | |||
4197 | dumps = XRESIZEVAR (impl, dumps, alloc)((impl *) xrealloc ((dumps), (alloc))); | |||
4198 | dumps->stack.embedded_init (count, current); | |||
4199 | } | |||
4200 | if (stream) | |||
4201 | dumps->stream = stream; | |||
4202 | ||||
4203 | unsigned n = dumps->indent; | |||
4204 | dumps->indent = 0; | |||
4205 | dumps->bol = true; | |||
4206 | dumps->stack.quick_push (m); | |||
4207 | if (m) | |||
4208 | { | |||
4209 | module_state *from = NULLnullptr; | |||
4210 | ||||
4211 | if (dumps->stack.length () > 1) | |||
4212 | from = dumps->stack[dumps->stack.length () - 2]; | |||
4213 | else | |||
4214 | dump (""); | |||
4215 | dump (from ? "Starting module %M (from %M)" | |||
4216 | : "Starting module %M", m, from); | |||
4217 | } | |||
4218 | ||||
4219 | return n; | |||
4220 | } | |||
4221 | ||||
4222 | /* Pop from dumping. Restore indentation to N. */ | |||
4223 | ||||
4224 | void dumper::pop (unsigned n) | |||
4225 | { | |||
4226 | if (!dumps) | |||
4227 | return; | |||
4228 | ||||
4229 | gcc_checking_assert (dump () && !dumps->indent)((void)(!(dump () && !dumps->indent) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4229, __FUNCTION__), 0 : 0)); | |||
4230 | if (module_state *m = dumps->stack[dumps->stack.length () - 1]) | |||
4231 | { | |||
4232 | module_state *from = (dumps->stack.length () > 1 | |||
4233 | ? dumps->stack[dumps->stack.length () - 2] : NULLnullptr); | |||
4234 | dump (from ? "Finishing module %M (returning to %M)" | |||
4235 | : "Finishing module %M", m, from); | |||
4236 | } | |||
4237 | dumps->stack.pop (); | |||
4238 | dumps->indent = n; | |||
4239 | if (!dumps->stack.length ()) | |||
4240 | { | |||
4241 | dump_end (module_dump_id, dumps->stream); | |||
4242 | dumps->stream = NULLnullptr; | |||
4243 | } | |||
4244 | } | |||
4245 | ||||
4246 | /* Dump a nested name for arbitrary tree T. Sometimes it won't have a | |||
4247 | name. */ | |||
4248 | ||||
4249 | bool | |||
4250 | dumper::impl::nested_name (tree t) | |||
4251 | { | |||
4252 | tree ti = NULL_TREE(tree) nullptr; | |||
4253 | int origin = -1; | |||
4254 | tree name = NULL_TREE(tree) nullptr; | |||
4255 | ||||
4256 | if (t && TREE_CODE (t)((enum tree_code) (t)->base.code) == TREE_BINFO) | |||
4257 | t = BINFO_TYPE (t)((contains_struct_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4257, __FUNCTION__, (TREE_BINFO)))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4257, __FUNCTION__))->typed.type); | |||
4258 | ||||
4259 | if (t && TYPE_P (t)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (t)->base.code))] == tcc_type)) | |||
4260 | t = TYPE_NAME (t)((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4260, __FUNCTION__))->type_common.name); | |||
4261 | ||||
4262 | if (t && DECL_P (t)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (t)->base.code))] == tcc_declaration)) | |||
4263 | { | |||
4264 | if (t == global_namespacecp_global_trees[CPTI_GLOBAL] || DECL_TEMPLATE_PARM_P (t)(((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4264, __FUNCTION__))->decl_common.lang_flag_0) && (((enum tree_code) (t)->base.code) == CONST_DECL || ((enum tree_code) (t)->base.code) == PARM_DECL || ((enum tree_code ) (t)->base.code) == TYPE_DECL || ((enum tree_code) (t)-> base.code) == TEMPLATE_DECL))) | |||
4265 | ; | |||
4266 | else if (tree ctx = DECL_CONTEXT (t)((contains_struct_check ((t), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4266, __FUNCTION__))->decl_minimal.context)) | |||
4267 | if (TREE_CODE (ctx)((enum tree_code) (ctx)->base.code) == TRANSLATION_UNIT_DECL | |||
4268 | || nested_name (ctx)) | |||
4269 | fputs ("::", stream); | |||
4270 | ||||
4271 | int use_tpl; | |||
4272 | ti = node_template_info (t, use_tpl); | |||
4273 | if (ti && TREE_CODE (TI_TEMPLATE (ti))((enum tree_code) (((struct tree_template_info*)(tree_check ( (ti), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4273, __FUNCTION__, (TEMPLATE_INFO))))->tmpl)->base.code ) == TEMPLATE_DECL | |||
4274 | && (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti))((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((((struct tree_template_info*)(tree_check ((ti), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4274, __FUNCTION__, (TEMPLATE_INFO))))->tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4274, __FUNCTION__, (TEMPLATE_DECL))))))))->result == t)) | |||
4275 | t = TI_TEMPLATE (ti)((struct tree_template_info*)(tree_check ((ti), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4275, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
4276 | tree not_tmpl = t; | |||
4277 | if (TREE_CODE (t)((enum tree_code) (t)->base.code) == TEMPLATE_DECL) | |||
4278 | { | |||
4279 | fputs ("template ", stream); | |||
4280 | not_tmpl = DECL_TEMPLATE_RESULT (t)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4280, __FUNCTION__, (TEMPLATE_DECL))))))))->result; | |||
4281 | } | |||
4282 | ||||
4283 | if (not_tmpl | |||
4284 | && DECL_P (not_tmpl)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (not_tmpl)->base.code))] == tcc_declaration) | |||
4285 | && DECL_LANG_SPECIFIC (not_tmpl)((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4285, __FUNCTION__))->decl_common.lang_specific) | |||
4286 | && DECL_MODULE_IMPORT_P (not_tmpl)(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4286, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4286, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p)) | |||
4287 | { | |||
4288 | /* We need to be careful here, so as to not explode on | |||
4289 | inconsistent data -- we're probably debugging, because | |||
4290 | Something Is Wrong. */ | |||
4291 | unsigned index = import_entity_index (t, true); | |||
4292 | if (!(index & ~(~0u >> 1))) | |||
4293 | origin = import_entity_module (index)->mod; | |||
4294 | else if (index > ~(~0u >> 1)) | |||
4295 | /* An imported partition member that we're emitting. */ | |||
4296 | origin = 0; | |||
4297 | else | |||
4298 | origin = -2; | |||
4299 | } | |||
4300 | ||||
4301 | name = DECL_NAME (t)((contains_struct_check ((t), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4301, __FUNCTION__))->decl_minimal.name) ? DECL_NAME (t)((contains_struct_check ((t), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4301, __FUNCTION__))->decl_minimal.name) | |||
4302 | : HAS_DECL_ASSEMBLER_NAME_P (t)((tree_contains_struct[(((enum tree_code) (t)->base.code)) ][(TS_DECL_WITH_VIS)])) ? DECL_ASSEMBLER_NAME_RAW (t)((contains_struct_check ((t), (TS_DECL_WITH_VIS), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4302, __FUNCTION__))->decl_with_vis.assembler_name) | |||
4303 | : NULL_TREE(tree) nullptr; | |||
4304 | } | |||
4305 | else | |||
4306 | name = t; | |||
4307 | ||||
4308 | if (name) | |||
4309 | switch (TREE_CODE (name)((enum tree_code) (name)->base.code)) | |||
4310 | { | |||
4311 | default: | |||
4312 | fputs ("#unnamed#", stream); | |||
4313 | break; | |||
4314 | ||||
4315 | case IDENTIFIER_NODE: | |||
4316 | fwrite (IDENTIFIER_POINTER (name)((const char *) (tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4316, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), 1, IDENTIFIER_LENGTH (name)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4316, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.len ), stream); | |||
4317 | break; | |||
4318 | ||||
4319 | case INTEGER_CST: | |||
4320 | print_hex (wi::to_wide (name), stream); | |||
4321 | break; | |||
4322 | ||||
4323 | case STRING_CST: | |||
4324 | /* If TREE_TYPE is NULL, this is a raw string. */ | |||
4325 | fwrite (TREE_STRING_POINTER (name)((const char *)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4325, __FUNCTION__, (STRING_CST)))->string.str)), 1, | |||
4326 | TREE_STRING_LENGTH (name)((tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4326, __FUNCTION__, (STRING_CST)))->string.length) - (TREE_TYPE (name)((contains_struct_check ((name), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4326, __FUNCTION__))->typed.type) != NULL_TREE(tree) nullptr), | |||
4327 | stream); | |||
4328 | break; | |||
4329 | } | |||
4330 | else | |||
4331 | fputs ("#null#", stream); | |||
4332 | ||||
4333 | if (origin >= 0) | |||
4334 | { | |||
4335 | const module_state *module = (*modules)[origin]; | |||
4336 | fprintf (stream, "@%s:%d", !module ? "" : !module->name ? "(unnamed)" | |||
4337 | : module->get_flatname (), origin); | |||
4338 | } | |||
4339 | else if (origin == -2) | |||
4340 | fprintf (stream, "@???"); | |||
4341 | ||||
4342 | if (ti) | |||
4343 | { | |||
4344 | tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti))(get_innermost_template_args ((((struct tree_template_info*)( tree_check ((ti), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4344, __FUNCTION__, (TEMPLATE_INFO))))->args), 1)); | |||
4345 | fputs ("<", stream); | |||
4346 | if (args) | |||
4347 | for (int ix = 0; ix != TREE_VEC_LENGTH (args)((tree_check ((args), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4347, __FUNCTION__, (TREE_VEC)))->base.u.length); ix++) | |||
4348 | { | |||
4349 | if (ix) | |||
4350 | fputs (",", stream); | |||
4351 | nested_name (TREE_VEC_ELT (args, ix)(*((const_cast<tree *> (tree_vec_elt_check ((args), (ix ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4351, __FUNCTION__)))))); | |||
4352 | } | |||
4353 | fputs (">", stream); | |||
4354 | } | |||
4355 | ||||
4356 | return true; | |||
4357 | } | |||
4358 | ||||
4359 | /* Formatted dumping. FORMAT begins with '+' do not emit a trailing | |||
4360 | new line. (Normally it is appended.) | |||
4361 | Escapes: | |||
4362 | %C - tree_code | |||
4363 | %I - identifier | |||
4364 | %M - module_state | |||
4365 | %N - name -- DECL_NAME | |||
4366 | %P - context:name pair | |||
4367 | %R - unsigned:unsigned ratio | |||
4368 | %S - symbol -- DECL_ASSEMBLER_NAME | |||
4369 | %U - long unsigned | |||
4370 | %V - version | |||
4371 | --- the following are printf-like, but without its flexibility | |||
4372 | %d - decimal int | |||
4373 | %p - pointer | |||
4374 | %s - string | |||
4375 | %u - unsigned int | |||
4376 | %x - hex int | |||
4377 | ||||
4378 | We do not implement the printf modifiers. */ | |||
4379 | ||||
4380 | bool | |||
4381 | dumper::operator () (const char *format, ...) | |||
4382 | { | |||
4383 | if (!(*this) ()) | |||
4384 | return false; | |||
4385 | ||||
4386 | bool no_nl = format[0] == '+'; | |||
4387 | format += no_nl; | |||
4388 | ||||
4389 | if (dumps->bol) | |||
4390 | { | |||
4391 | /* Module import indent. */ | |||
4392 | if (unsigned depth = dumps->stack.length () - 1) | |||
4393 | { | |||
4394 | const char *prefix = ">>>>"; | |||
4395 | fprintf (dumps->stream, (depth <= strlen (prefix) | |||
4396 | ? &prefix[strlen (prefix) - depth] | |||
4397 | : ">.%d.>"), depth); | |||
4398 | } | |||
4399 | ||||
4400 | /* Local indent. */ | |||
4401 | if (unsigned indent = dumps->indent) | |||
4402 | { | |||
4403 | const char *prefix = " "; | |||
4404 | fprintf (dumps->stream, (indent <= strlen (prefix) | |||
4405 | ? &prefix[strlen (prefix) - indent] | |||
4406 | : " .%d. "), indent); | |||
4407 | } | |||
4408 | dumps->bol = false; | |||
4409 | } | |||
4410 | ||||
4411 | va_list args; | |||
4412 | va_start (args, format)__builtin_va_start(args, format); | |||
4413 | while (const char *esc = strchr (format, '%')) | |||
4414 | { | |||
4415 | fwrite (format, 1, (size_t)(esc - format), dumps->stream); | |||
4416 | format = ++esc; | |||
4417 | switch (*format++) | |||
4418 | { | |||
4419 | default: | |||
4420 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4420, __FUNCTION__)); | |||
4421 | ||||
4422 | case '%': | |||
4423 | fputc ('%', dumps->stream); | |||
4424 | break; | |||
4425 | ||||
4426 | case 'C': /* Code */ | |||
4427 | { | |||
4428 | tree_code code = (tree_code)va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4429 | fputs (get_tree_code_name (code), dumps->stream); | |||
4430 | } | |||
4431 | break; | |||
4432 | ||||
4433 | case 'I': /* Identifier. */ | |||
4434 | { | |||
4435 | tree t = va_arg (args, tree)__builtin_va_arg(args, tree); | |||
4436 | dumps->nested_name (t); | |||
4437 | } | |||
4438 | break; | |||
4439 | ||||
4440 | case 'M': /* Module. */ | |||
4441 | { | |||
4442 | const char *str = "(none)"; | |||
4443 | if (module_state *m = va_arg (args, module_state *)__builtin_va_arg(args, module_state *)) | |||
4444 | { | |||
4445 | if (!m->has_location ()) | |||
4446 | str = "(detached)"; | |||
4447 | else | |||
4448 | str = m->get_flatname (); | |||
4449 | } | |||
4450 | fputs (str, dumps->stream); | |||
4451 | } | |||
4452 | break; | |||
4453 | ||||
4454 | case 'N': /* Name. */ | |||
4455 | { | |||
4456 | tree t = va_arg (args, tree)__builtin_va_arg(args, tree); | |||
4457 | while (t && TREE_CODE (t)((enum tree_code) (t)->base.code) == OVERLOAD) | |||
4458 | t = OVL_FUNCTION (t)(((struct tree_overload*)(tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4458, __FUNCTION__, (OVERLOAD))))->function); | |||
4459 | fputc ('\'', dumps->stream); | |||
4460 | dumps->nested_name (t); | |||
4461 | fputc ('\'', dumps->stream); | |||
4462 | } | |||
4463 | break; | |||
4464 | ||||
4465 | case 'P': /* Pair. */ | |||
4466 | { | |||
4467 | tree ctx = va_arg (args, tree)__builtin_va_arg(args, tree); | |||
4468 | tree name = va_arg (args, tree)__builtin_va_arg(args, tree); | |||
4469 | fputc ('\'', dumps->stream); | |||
4470 | dumps->nested_name (ctx); | |||
4471 | if (ctx && ctx != global_namespacecp_global_trees[CPTI_GLOBAL]) | |||
4472 | fputs ("::", dumps->stream); | |||
4473 | dumps->nested_name (name); | |||
4474 | fputc ('\'', dumps->stream); | |||
4475 | } | |||
4476 | break; | |||
4477 | ||||
4478 | case 'R': /* Ratio */ | |||
4479 | { | |||
4480 | unsigned a = va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4481 | unsigned b = va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4482 | fprintf (dumps->stream, "%.1f", (float) a / (b + !b)); | |||
4483 | } | |||
4484 | break; | |||
4485 | ||||
4486 | case 'S': /* Symbol name */ | |||
4487 | { | |||
4488 | tree t = va_arg (args, tree)__builtin_va_arg(args, tree); | |||
4489 | if (t && TYPE_P (t)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (t)->base.code))] == tcc_type)) | |||
4490 | t = TYPE_NAME (t)((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4490, __FUNCTION__))->type_common.name); | |||
4491 | if (t && HAS_DECL_ASSEMBLER_NAME_P (t)((tree_contains_struct[(((enum tree_code) (t)->base.code)) ][(TS_DECL_WITH_VIS)])) | |||
4492 | && DECL_ASSEMBLER_NAME_SET_P (t)(((contains_struct_check ((t), (TS_DECL_WITH_VIS), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4492, __FUNCTION__))->decl_with_vis.assembler_name) != ( tree) nullptr)) | |||
4493 | { | |||
4494 | fputc ('(', dumps->stream); | |||
4495 | fputs (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))((const char *) (tree_check ((decl_assembler_name (t)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4495, __FUNCTION__, (IDENTIFIER_NODE)))->identifier.id.str ), | |||
4496 | dumps->stream); | |||
4497 | fputc (')', dumps->stream); | |||
4498 | } | |||
4499 | } | |||
4500 | break; | |||
4501 | ||||
4502 | case 'U': /* long unsigned. */ | |||
4503 | { | |||
4504 | unsigned long u = va_arg (args, unsigned long)__builtin_va_arg(args, unsigned long); | |||
4505 | fprintf (dumps->stream, "%lu", u); | |||
4506 | } | |||
4507 | break; | |||
4508 | ||||
4509 | case 'V': /* Verson. */ | |||
4510 | { | |||
4511 | unsigned v = va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4512 | verstr_t string; | |||
4513 | ||||
4514 | version2string (v, string); | |||
4515 | fputs (string, dumps->stream); | |||
4516 | } | |||
4517 | break; | |||
4518 | ||||
4519 | case 'c': /* Character. */ | |||
4520 | { | |||
4521 | int c = va_arg (args, int)__builtin_va_arg(args, int); | |||
4522 | fputc (c, dumps->stream); | |||
4523 | } | |||
4524 | break; | |||
4525 | ||||
4526 | case 'd': /* Decimal Int. */ | |||
4527 | { | |||
4528 | int d = va_arg (args, int)__builtin_va_arg(args, int); | |||
4529 | fprintf (dumps->stream, "%d", d); | |||
4530 | } | |||
4531 | break; | |||
4532 | ||||
4533 | case 'p': /* Pointer. */ | |||
4534 | { | |||
4535 | void *p = va_arg (args, void *)__builtin_va_arg(args, void *); | |||
4536 | fprintf (dumps->stream, "%p", p); | |||
4537 | } | |||
4538 | break; | |||
4539 | ||||
4540 | case 's': /* String. */ | |||
4541 | { | |||
4542 | const char *s = va_arg (args, char *)__builtin_va_arg(args, char *); | |||
4543 | gcc_checking_assert (s)((void)(!(s) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4543, __FUNCTION__), 0 : 0)); | |||
4544 | fputs (s, dumps->stream); | |||
4545 | } | |||
4546 | break; | |||
4547 | ||||
4548 | case 'u': /* Unsigned. */ | |||
4549 | { | |||
4550 | unsigned u = va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4551 | fprintf (dumps->stream, "%u", u); | |||
4552 | } | |||
4553 | break; | |||
4554 | ||||
4555 | case 'x': /* Hex. */ | |||
4556 | { | |||
4557 | unsigned x = va_arg (args, unsigned)__builtin_va_arg(args, unsigned); | |||
4558 | fprintf (dumps->stream, "%x", x); | |||
4559 | } | |||
4560 | break; | |||
4561 | } | |||
4562 | } | |||
4563 | fputs (format, dumps->stream); | |||
4564 | va_end (args)__builtin_va_end(args); | |||
4565 | if (!no_nl) | |||
4566 | { | |||
4567 | dumps->bol = true; | |||
4568 | fputc ('\n', dumps->stream); | |||
4569 | } | |||
4570 | return true; | |||
4571 | } | |||
4572 | ||||
4573 | struct note_def_cache_hasher : ggc_cache_ptr_hash<tree_node> | |||
4574 | { | |||
4575 | static int keep_cache_entry (tree t) | |||
4576 | { | |||
4577 | if (!CHECKING_P1) | |||
4578 | /* GTY is unfortunately not clever enough to conditionalize | |||
4579 | this. */ | |||
4580 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4580, __FUNCTION__)); | |||
4581 | ||||
4582 | if (ggc_marked_p (t)) | |||
4583 | return -1; | |||
4584 | ||||
4585 | unsigned n = dump.push (NULLnullptr); | |||
4586 | /* This might or might not be an error. We should note its | |||
4587 | dropping whichever. */ | |||
4588 | dump () && dump ("Dropping %N from note_defs table", t); | |||
4589 | dump.pop (n); | |||
4590 | ||||
4591 | return 0; | |||
4592 | } | |||
4593 | }; | |||
4594 | ||||
4595 | /* We should stream each definition at most once. | |||
4596 | This needs to be a cache because there are cases where a definition | |||
4597 | ends up being not retained, and we need to drop those so we don't | |||
4598 | get confused if memory is reallocated. */ | |||
4599 | typedef hash_table<note_def_cache_hasher> note_defs_table_t; | |||
4600 | static GTY((cache)) note_defs_table_t *note_defs; | |||
4601 | ||||
4602 | void | |||
4603 | trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | |||
4604 | bool installing ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
4605 | { | |||
4606 | #if CHECKING_P1 | |||
4607 | tree *slot = note_defs->find_slot (decl, installing ? INSERT : NO_INSERT); | |||
4608 | tree not_tmpl = STRIP_TEMPLATE (decl)(((enum tree_code) (decl)->base.code) == TEMPLATE_DECL ? ( (struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4608, __FUNCTION__, (TEMPLATE_DECL))))))))->result : decl ); | |||
4609 | if (installing) | |||
4610 | { | |||
4611 | /* We must be inserting for the first time. */ | |||
4612 | gcc_assert (!*slot)((void)(!(!*slot) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4612, __FUNCTION__), 0 : 0)); | |||
4613 | *slot = decl; | |||
4614 | } | |||
4615 | else | |||
4616 | /* If this is not the mergeable entity, it should not be in the | |||
4617 | table. If it is a non-global-module mergeable entity, it | |||
4618 | should be in the table. Global module entities could have been | |||
4619 | defined textually in the current TU and so might or might not | |||
4620 | be present. */ | |||
4621 | gcc_assert (!is_duplicate (decl)((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4622 | ? !slot((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4623 | : (slot((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4624 | || !DECL_LANG_SPECIFIC (not_tmpl)((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4625 | || !DECL_MODULE_PURVIEW_P (not_tmpl)((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4626 | || (!DECL_MODULE_IMPORT_P (not_tmpl)((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)) | |||
4627 | && header_module_p ())))((void)(!(!is_duplicate (decl) ? !slot : (slot || !((contains_struct_check ((not_tmpl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4624, __FUNCTION__))->decl_common.lang_specific) || !((( contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4625, __FUNCTION__))->decl_common.lang_specific)->u.base .module_purview_p) || (!(((contains_struct_check (((tree_not_check ((not_tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__, (TEMPLATE_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4626, __FUNCTION__))->decl_common.lang_specific)->u.base .module_import_p) && header_module_p ()))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4627, __FUNCTION__), 0 : 0)); | |||
4628 | ||||
4629 | if (not_tmpl != decl) | |||
4630 | gcc_assert (!note_defs->find_slot (not_tmpl, NO_INSERT))((void)(!(!note_defs->find_slot (not_tmpl, NO_INSERT)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4630, __FUNCTION__), 0 : 0)); | |||
4631 | #endif | |||
4632 | } | |||
4633 | ||||
4634 | void | |||
4635 | trees_out::assert_definition (tree decl ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
4636 | { | |||
4637 | #if CHECKING_P1 | |||
4638 | tree *slot = note_defs->find_slot (decl, INSERT); | |||
4639 | gcc_assert (!*slot)((void)(!(!*slot) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4639, __FUNCTION__), 0 : 0)); | |||
4640 | *slot = decl; | |||
4641 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) == TEMPLATE_DECL) | |||
4642 | gcc_assert (!note_defs->find_slot (DECL_TEMPLATE_RESULT (decl), NO_INSERT))((void)(!(!note_defs->find_slot (((struct tree_template_decl *)(const_cast<union tree_node *> ((((tree_check ((decl ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4642, __FUNCTION__, (TEMPLATE_DECL))))))))->result, NO_INSERT )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4642, __FUNCTION__), 0 : 0)); | |||
4643 | #endif | |||
4644 | } | |||
4645 | ||||
4646 | /********************************************************************/ | |||
4647 | static bool | |||
4648 | noisy_p () | |||
4649 | { | |||
4650 | if (quiet_flagglobal_options.x_quiet_flag) | |||
4651 | return false; | |||
4652 | ||||
4653 | pp_needs_newline (global_dc->printer)(global_dc->printer)->need_newline = true; | |||
4654 | diagnostic_set_last_function (global_dc, (diagnostic_info *) NULL)(global_dc)->x_data = ((((diagnostic_info *) nullptr) && ((tree) ((diagnostic_info *) nullptr)->x_data)) ? ((tree) ((diagnostic_info *) nullptr)->x_data) : current_function_decl ); | |||
4655 | ||||
4656 | return true; | |||
4657 | } | |||
4658 | ||||
4659 | /* Set the cmi repo. Strip trailing '/', '.' becomes NULL. */ | |||
4660 | ||||
4661 | static void | |||
4662 | set_cmi_repo (const char *r) | |||
4663 | { | |||
4664 | XDELETEVEC (cmi_repo)free ((void*) (cmi_repo)); | |||
4665 | XDELETEVEC (cmi_path)free ((void*) (cmi_path)); | |||
4666 | cmi_path_alloc = 0; | |||
4667 | ||||
4668 | cmi_repo = NULLnullptr; | |||
4669 | cmi_repo_length = 0; | |||
4670 | ||||
4671 | if (!r || !r[0]) | |||
4672 | return; | |||
4673 | ||||
4674 | size_t len = strlen (r); | |||
4675 | cmi_repo = XNEWVEC (char, len + 1)((char *) xmalloc (sizeof (char) * (len + 1))); | |||
4676 | memcpy (cmi_repo, r, len + 1); | |||
4677 | ||||
4678 | if (len > 1 && IS_DIR_SEPARATOR (cmi_repo[len-1])(((cmi_repo[len-1]) == '/') || (((cmi_repo[len-1]) == '\\') && (0)))) | |||
4679 | len--; | |||
4680 | if (len == 1 && cmi_repo[0] == '.') | |||
4681 | len--; | |||
4682 | cmi_repo[len] = 0; | |||
4683 | cmi_repo_length = len; | |||
4684 | } | |||
4685 | ||||
4686 | /* TO is a repo-relative name. Provide one that we may use from where | |||
4687 | we are. */ | |||
4688 | ||||
4689 | static const char * | |||
4690 | maybe_add_cmi_prefix (const char *to, size_t *len_p = NULLnullptr) | |||
4691 | { | |||
4692 | size_t len = len_p || cmi_repo_length ? strlen (to) : 0; | |||
4693 | ||||
4694 | if (cmi_repo_length && !IS_ABSOLUTE_PATH (to)(((((to)[0]) == '/') || ((((to)[0]) == '\\') && (0))) || ((to)[0] && ((to)[1] == ':') && (0)))) | |||
4695 | { | |||
4696 | if (cmi_path_alloc < cmi_repo_length + len + 2) | |||
4697 | { | |||
4698 | XDELETEVEC (cmi_path)free ((void*) (cmi_path)); | |||
4699 | cmi_path_alloc = cmi_repo_length + len * 2 + 2; | |||
4700 | cmi_path = XNEWVEC (char, cmi_path_alloc)((char *) xmalloc (sizeof (char) * (cmi_path_alloc))); | |||
4701 | ||||
4702 | memcpy (cmi_path, cmi_repo, cmi_repo_length); | |||
4703 | cmi_path[cmi_repo_length] = DIR_SEPARATOR'/'; | |||
4704 | } | |||
4705 | ||||
4706 | memcpy (&cmi_path[cmi_repo_length + 1], to, len + 1); | |||
4707 | len += cmi_repo_length + 1; | |||
4708 | to = cmi_path; | |||
4709 | } | |||
4710 | ||||
4711 | if (len_p) | |||
4712 | *len_p = len; | |||
4713 | ||||
4714 | return to; | |||
4715 | } | |||
4716 | ||||
4717 | /* Try and create the directories of PATH. */ | |||
4718 | ||||
4719 | static void | |||
4720 | create_dirs (char *path) | |||
4721 | { | |||
4722 | /* Try and create the missing directories. */ | |||
4723 | for (char *base = path; *base; base++) | |||
4724 | if (IS_DIR_SEPARATOR (*base)(((*base) == '/') || (((*base) == '\\') && (0)))) | |||
4725 | { | |||
4726 | char sep = *base; | |||
4727 | *base = 0; | |||
4728 | int failed = mkdir (path, S_IRWXU(0400|0200|0100) | S_IRWXG((0400|0200|0100) >> 3) | S_IRWXO(((0400|0200|0100) >> 3) >> 3)); | |||
4729 | dump () && dump ("Mkdir ('%s') errno:=%u", path, failed ? errno(*__errno_location ()) : 0); | |||
4730 | *base = sep; | |||
4731 | if (failed | |||
4732 | /* Maybe racing with another creator (of a *different* | |||
4733 | module). */ | |||
4734 | && errno(*__errno_location ()) != EEXIST17) | |||
4735 | break; | |||
4736 | } | |||
4737 | } | |||
4738 | ||||
4739 | /* Given a CLASSTYPE_DECL_LIST VALUE get the template friend decl, | |||
4740 | if that's what this is. */ | |||
4741 | ||||
4742 | static tree | |||
4743 | friend_from_decl_list (tree frnd) | |||
4744 | { | |||
4745 | tree res = frnd; | |||
4746 | ||||
4747 | if (TREE_CODE (frnd)((enum tree_code) (frnd)->base.code) != TEMPLATE_DECL) | |||
4748 | { | |||
4749 | tree tmpl = NULL_TREE(tree) nullptr; | |||
4750 | if (TYPE_P (frnd)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (frnd)->base.code))] == tcc_type)) | |||
4751 | { | |||
4752 | res = TYPE_NAME (frnd)((tree_class_check ((frnd), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4752, __FUNCTION__))->type_common.name); | |||
4753 | if (CLASS_TYPE_P (frnd)(((((enum tree_code) (frnd)->base.code)) == RECORD_TYPE || (((enum tree_code) (frnd)->base.code)) == UNION_TYPE) && ((tree_class_check ((frnd), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4753, __FUNCTION__))->type_common.lang_flag_5)) | |||
4754 | && CLASSTYPE_TEMPLATE_INFO (frnd)(((tree_class_check (((tree_check3 ((frnd), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4754, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4754, __FUNCTION__))->type_non_common.lang_1))) | |||
4755 | tmpl = CLASSTYPE_TI_TEMPLATE (frnd)((struct tree_template_info*)(tree_check (((((tree_class_check (((tree_check3 ((frnd), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4755, __FUNCTION__, (RECORD_TYPE), (UNION_TYPE), (QUAL_UNION_TYPE )))), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4755, __FUNCTION__))->type_non_common.lang_1))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4755, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
4756 | } | |||
4757 | else if (DECL_TEMPLATE_INFO (frnd)(((contains_struct_check ((template_info_decl_check ((frnd), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4757, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4757, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)) | |||
4758 | { | |||
4759 | tmpl = DECL_TI_TEMPLATE (frnd)((struct tree_template_info*)(tree_check (((((contains_struct_check ((template_info_decl_check ((frnd), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4759, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4759, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4759, __FUNCTION__, (TEMPLATE_INFO))))->tmpl; | |||
4760 | if (TREE_CODE (tmpl)((enum tree_code) (tmpl)->base.code) != TEMPLATE_DECL) | |||
4761 | tmpl = NULL_TREE(tree) nullptr; | |||
4762 | } | |||
4763 | ||||
4764 | if (tmpl && DECL_TEMPLATE_RESULT (tmpl)((struct tree_template_decl *)(const_cast<union tree_node * > ((((tree_check ((tmpl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4764, __FUNCTION__, (TEMPLATE_DECL))))))))->result == res) | |||
4765 | res = tmpl; | |||
4766 | } | |||
4767 | ||||
4768 | return res; | |||
4769 | } | |||
4770 | ||||
4771 | static tree | |||
4772 | find_enum_member (tree ctx, tree name) | |||
4773 | { | |||
4774 | for (tree values = TYPE_VALUES (ctx)((tree_check ((ctx), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4774, __FUNCTION__, (ENUMERAL_TYPE)))->type_non_common.values ); | |||
4775 | values; values = TREE_CHAIN (values)((contains_struct_check ((values), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4775, __FUNCTION__))->common.chain)) | |||
4776 | if (DECL_NAME (TREE_VALUE (values))((contains_struct_check ((((tree_check ((values), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4776, __FUNCTION__, (TREE_LIST)))->list.value)), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4776, __FUNCTION__))->decl_minimal.name) == name) | |||
4777 | return TREE_VALUE (values)((tree_check ((values), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4777, __FUNCTION__, (TREE_LIST)))->list.value); | |||
4778 | ||||
4779 | return NULL_TREE(tree) nullptr; | |||
4780 | } | |||
4781 | ||||
4782 | /********************************************************************/ | |||
4783 | /* Instrumentation gathered writing bytes. */ | |||
4784 | ||||
4785 | void | |||
4786 | bytes_out::instrument () | |||
4787 | { | |||
4788 | dump ("Wrote %u bytes in %u blocks", lengths[3], spans[3]); | |||
4789 | dump ("Wrote %u bits in %u bytes", lengths[0] + lengths[1], lengths[2]); | |||
4790 | for (unsigned ix = 0; ix < 2; ix++) | |||
4791 | dump (" %u %s spans of %R bits", spans[ix], | |||
4792 | ix ? "one" : "zero", lengths[ix], spans[ix]); | |||
4793 | dump (" %u blocks with %R bits padding", spans[2], | |||
4794 | lengths[2] * 8 - (lengths[0] + lengths[1]), spans[2]); | |||
4795 | } | |||
4796 | ||||
4797 | /* Instrumentation gathered writing trees. */ | |||
4798 | void | |||
4799 | trees_out::instrument () | |||
4800 | { | |||
4801 | if (dump ("")) | |||
4802 | { | |||
4803 | bytes_out::instrument (); | |||
4804 | dump ("Wrote:"); | |||
4805 | dump (" %u decl trees", decl_val_count); | |||
4806 | dump (" %u other trees", tree_val_count); | |||
4807 | dump (" %u back references", back_ref_count); | |||
4808 | dump (" %u null trees", null_count); | |||
4809 | } | |||
4810 | } | |||
4811 | ||||
4812 | /* Setup and teardown for a tree walk. */ | |||
4813 | ||||
4814 | void | |||
4815 | trees_out::begin () | |||
4816 | { | |||
4817 | gcc_assert (!streaming_p () || !tree_map.elements ())((void)(!(!streaming_p () || !tree_map.elements ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4817, __FUNCTION__), 0 : 0)); | |||
4818 | ||||
4819 | mark_trees (); | |||
4820 | if (streaming_p ()) | |||
4821 | parent::begin (); | |||
4822 | } | |||
4823 | ||||
4824 | unsigned | |||
4825 | trees_out::end (elf_out *sink, unsigned name, unsigned *crc_ptr) | |||
4826 | { | |||
4827 | gcc_checking_assert (streaming_p ())((void)(!(streaming_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4827, __FUNCTION__), 0 : 0)); | |||
4828 | ||||
4829 | unmark_trees (); | |||
4830 | return parent::end (sink, name, crc_ptr); | |||
4831 | } | |||
4832 | ||||
4833 | void | |||
4834 | trees_out::end () | |||
4835 | { | |||
4836 | gcc_assert (!streaming_p ())((void)(!(!streaming_p ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4836, __FUNCTION__), 0 : 0)); | |||
4837 | ||||
4838 | unmark_trees (); | |||
4839 | /* Do not parent::end -- we weren't streaming. */ | |||
4840 | } | |||
4841 | ||||
4842 | void | |||
4843 | trees_out::mark_trees () | |||
4844 | { | |||
4845 | if (size_t size = tree_map.elements ()) | |||
4846 | { | |||
4847 | /* This isn't our first rodeo, destroy and recreate the | |||
4848 | tree_map. I'm a bad bad man. Use the previous size as a | |||
4849 | guess for the next one (so not all bad). */ | |||
4850 | tree_map.~ptr_int_hash_map (); | |||
4851 | new (&tree_map) ptr_int_hash_map (size); | |||
4852 | } | |||
4853 | ||||
4854 | /* Install the fixed trees, with +ve references. */ | |||
4855 | unsigned limit = fixed_trees->length (); | |||
4856 | for (unsigned ix = 0; ix != limit; ix++) | |||
4857 | { | |||
4858 | tree val = (*fixed_trees)[ix]; | |||
4859 | bool existed = tree_map.put (val, ix + tag_fixed); | |||
4860 | gcc_checking_assert (!TREE_VISITED (val) && !existed)((void)(!(!((val)->base.visited) && !existed) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4860, __FUNCTION__), 0 : 0)); | |||
4861 | TREE_VISITED (val)((val)->base.visited) = true; | |||
4862 | } | |||
4863 | ||||
4864 | ref_num = 0; | |||
4865 | } | |||
4866 | ||||
4867 | /* Unmark the trees we encountered */ | |||
4868 | ||||
4869 | void | |||
4870 | trees_out::unmark_trees () | |||
4871 | { | |||
4872 | ptr_int_hash_map::iterator end (tree_map.end ()); | |||
4873 | for (ptr_int_hash_map::iterator iter (tree_map.begin ()); iter != end; ++iter) | |||
4874 | { | |||
4875 | tree node = reinterpret_cast<tree> ((*iter).first); | |||
4876 | int ref = (*iter).second; | |||
4877 | /* We should have visited the node, and converted its mergeable | |||
4878 | reference to a regular reference. */ | |||
4879 | gcc_checking_assert (TREE_VISITED (node)((void)(!(((node)->base.visited) && (ref <= tag_backref || ref >= tag_fixed)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4880, __FUNCTION__), 0 : 0)) | |||
4880 | && (ref <= tag_backref || ref >= tag_fixed))((void)(!(((node)->base.visited) && (ref <= tag_backref || ref >= tag_fixed)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4880, __FUNCTION__), 0 : 0)); | |||
4881 | TREE_VISITED (node)((node)->base.visited) = false; | |||
4882 | } | |||
4883 | } | |||
4884 | ||||
4885 | /* Mark DECL for by-value walking. We do this by inserting it into | |||
4886 | the tree map with a reference of zero. May be called multiple | |||
4887 | times on the same node. */ | |||
4888 | ||||
4889 | void | |||
4890 | trees_out::mark_by_value (tree decl) | |||
4891 | { | |||
4892 | gcc_checking_assert (DECL_P (decl)((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (decl)->base.code))] == tcc_declaration ) || ((enum tree_code) (decl)->base.code) == INTEGER_CST || ((enum tree_code) (decl)->base.code) == TREE_BINFO) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4895, __FUNCTION__), 0 : 0)) | |||
4893 | /* Enum consts are INTEGER_CSTS. */((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (decl)->base.code))] == tcc_declaration ) || ((enum tree_code) (decl)->base.code) == INTEGER_CST || ((enum tree_code) (decl)->base.code) == TREE_BINFO) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4895, __FUNCTION__), 0 : 0)) | |||
4894 | || TREE_CODE (decl) == INTEGER_CST((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (decl)->base.code))] == tcc_declaration ) || ((enum tree_code) (decl)->base.code) == INTEGER_CST || ((enum tree_code) (decl)->base.code) == TREE_BINFO) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4895, __FUNCTION__), 0 : 0)) | |||
4895 | || TREE_CODE (decl) == TREE_BINFO)((void)(!((tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) (decl)->base.code))] == tcc_declaration ) || ((enum tree_code) (decl)->base.code) == INTEGER_CST || ((enum tree_code) (decl)->base.code) == TREE_BINFO) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4895, __FUNCTION__), 0 : 0)); | |||
4896 | ||||
4897 | if (TREE_VISITED (decl)((decl)->base.visited)) | |||
4898 | /* Must already be forced or fixed. */ | |||
4899 | gcc_checking_assert (*tree_map.get (decl) >= tag_value)((void)(!(*tree_map.get (decl) >= tag_value) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4899, __FUNCTION__), 0 : 0)); | |||
4900 | else | |||
4901 | { | |||
4902 | bool existed = tree_map.put (decl, tag_value); | |||
4903 | gcc_checking_assert (!existed)((void)(!(!existed) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4903, __FUNCTION__), 0 : 0)); | |||
4904 | TREE_VISITED (decl)((decl)->base.visited) = true; | |||
4905 | } | |||
4906 | } | |||
4907 | ||||
4908 | int | |||
4909 | trees_out::get_tag (tree t) | |||
4910 | { | |||
4911 | gcc_checking_assert (TREE_VISITED (t))((void)(!(((t)->base.visited)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4911, __FUNCTION__), 0 : 0)); | |||
4912 | return *tree_map.get (t); | |||
4913 | } | |||
4914 | ||||
4915 | /* Insert T into the map, return its tag number. */ | |||
4916 | ||||
4917 | int | |||
4918 | trees_out::insert (tree t, walk_kind walk) | |||
4919 | { | |||
4920 | gcc_checking_assert (walk != WK_normal || !TREE_VISITED (t))((void)(!(walk != WK_normal || !((t)->base.visited)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4920, __FUNCTION__), 0 : 0)); | |||
4921 | int tag = --ref_num; | |||
4922 | bool existed; | |||
4923 | int &slot = tree_map.get_or_insert (t, &existed); | |||
4924 | gcc_checking_assert (TREE_VISITED (t) == existed((void)(!(((t)->base.visited) == existed && (!existed || (walk == WK_value && slot == tag_value))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4926, __FUNCTION__), 0 : 0)) | |||
4925 | && (!existed((void)(!(((t)->base.visited) == existed && (!existed || (walk == WK_value && slot == tag_value))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4926, __FUNCTION__), 0 : 0)) | |||
4926 | || (walk == WK_value && slot == tag_value)))((void)(!(((t)->base.visited) == existed && (!existed || (walk == WK_value && slot == tag_value))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4926, __FUNCTION__), 0 : 0)); | |||
4927 | TREE_VISITED (t)((t)->base.visited) = true; | |||
4928 | slot = tag; | |||
4929 | ||||
4930 | return tag; | |||
4931 | } | |||
4932 | ||||
4933 | /* Insert T into the backreference array. Return its back reference | |||
4934 | number. */ | |||
4935 | ||||
4936 | int | |||
4937 | trees_in::insert (tree t) | |||
4938 | { | |||
4939 | gcc_checking_assert (t || get_overrun ())((void)(!(t || get_overrun ()) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4939, __FUNCTION__), 0 : 0)); | |||
4940 | back_refs.safe_push (t); | |||
4941 | return -(int)back_refs.length (); | |||
4942 | } | |||
4943 | ||||
4944 | /* A chained set of decls. */ | |||
4945 | ||||
4946 | void | |||
4947 | trees_out::chained_decls (tree decls) | |||
4948 | { | |||
4949 | for (; decls; decls = DECL_CHAIN (decls)(((contains_struct_check (((contains_struct_check ((decls), ( TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4949, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4949, __FUNCTION__))->common.chain))) | |||
4950 | { | |||
4951 | if (VAR_OR_FUNCTION_DECL_P (decls)(((enum tree_code) (decls)->base.code) == VAR_DECL || ((enum tree_code) (decls)->base.code) == FUNCTION_DECL) | |||
4952 | && DECL_LOCAL_DECL_P (decls)((contains_struct_check (((tree_check2 ((decls), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4952, __FUNCTION__, (VAR_DECL), (FUNCTION_DECL)))), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4952, __FUNCTION__))->decl_common.lang_flag_0)) | |||
4953 | { | |||
4954 | /* Make sure this is the first encounter, and mark for | |||
4955 | walk-by-value. */ | |||
4956 | gcc_checking_assert (!TREE_VISITED (decls)((void)(!(!((decls)->base.visited) && !(((contains_struct_check ((template_info_decl_check ((decls), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__), 0 : 0)) | |||
4957 | && !DECL_TEMPLATE_INFO (decls))((void)(!(!((decls)->base.visited) && !(((contains_struct_check ((template_info_decl_check ((decls), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__)), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__))->decl_common.lang_specific) ->u. min.template_info)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4957, __FUNCTION__), 0 : 0)); | |||
4958 | mark_by_value (decls); | |||
4959 | } | |||
4960 | tree_node (decls); | |||
4961 | } | |||
4962 | tree_node (NULL_TREE(tree) nullptr); | |||
4963 | } | |||
4964 | ||||
4965 | tree | |||
4966 | trees_in::chained_decls () | |||
4967 | { | |||
4968 | tree decls = NULL_TREE(tree) nullptr; | |||
4969 | for (tree *chain = &decls;;) | |||
4970 | if (tree decl = tree_node ()) | |||
4971 | { | |||
4972 | if (!DECL_P (decl)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (decl)->base.code))] == tcc_declaration) || DECL_CHAIN (decl)(((contains_struct_check (((contains_struct_check ((decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4972, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4972, __FUNCTION__))->common.chain))) | |||
4973 | { | |||
4974 | set_overrun (); | |||
4975 | break; | |||
4976 | } | |||
4977 | *chain = decl; | |||
4978 | chain = &DECL_CHAIN (decl)(((contains_struct_check (((contains_struct_check ((decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4978, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4978, __FUNCTION__))->common.chain)); | |||
4979 | } | |||
4980 | else | |||
4981 | break; | |||
4982 | ||||
4983 | return decls; | |||
4984 | } | |||
4985 | ||||
4986 | /* A vector of decls following DECL_CHAIN. */ | |||
4987 | ||||
4988 | void | |||
4989 | trees_out::vec_chained_decls (tree decls) | |||
4990 | { | |||
4991 | if (streaming_p ()) | |||
4992 | { | |||
4993 | unsigned len = 0; | |||
4994 | ||||
4995 | for (tree decl = decls; decl; decl = DECL_CHAIN (decl)(((contains_struct_check (((contains_struct_check ((decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4995, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 4995, __FUNCTION__))->common.chain))) | |||
4996 | len++; | |||
4997 | u (len); | |||
4998 | } | |||
4999 | ||||
5000 | for (tree decl = decls; decl; decl = DECL_CHAIN (decl)(((contains_struct_check (((contains_struct_check ((decl), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5000, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5000, __FUNCTION__))->common.chain))) | |||
5001 | { | |||
5002 | if (DECL_IMPLICIT_TYPEDEF_P (decl)(((enum tree_code) (decl)->base.code) == TYPE_DECL && ((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5002, __FUNCTION__))->decl_common.lang_flag_2)) | |||
5003 | && TYPE_NAME (TREE_TYPE (decl))((tree_class_check ((((contains_struct_check ((decl), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5003, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5003, __FUNCTION__))->type_common.name) != decl) | |||
5004 | /* An anonynmous struct with a typedef name. An odd thing to | |||
5005 | write. */ | |||
5006 | tree_node (NULL_TREE(tree) nullptr); | |||
5007 | else | |||
5008 | tree_node (decl); | |||
5009 | } | |||
5010 | } | |||
5011 | ||||
5012 | vec<tree, va_heap> * | |||
5013 | trees_in::vec_chained_decls () | |||
5014 | { | |||
5015 | vec<tree, va_heap> *v = NULLnullptr; | |||
5016 | ||||
5017 | if (unsigned len = u ()) | |||
5018 | { | |||
5019 | vec_alloc (v, len); | |||
5020 | ||||
5021 | for (unsigned ix = 0; ix < len; ix++) | |||
5022 | { | |||
5023 | tree decl = tree_node (); | |||
5024 | if (decl && !DECL_P (decl)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (decl)->base.code))] == tcc_declaration)) | |||
5025 | { | |||
5026 | set_overrun (); | |||
5027 | break; | |||
5028 | } | |||
5029 | v->quick_push (decl); | |||
5030 | } | |||
5031 | ||||
5032 | if (get_overrun ()) | |||
5033 | { | |||
5034 | vec_free (v); | |||
5035 | v = NULLnullptr; | |||
5036 | } | |||
5037 | } | |||
5038 | ||||
5039 | return v; | |||
5040 | } | |||
5041 | ||||
5042 | /* A vector of trees. */ | |||
5043 | ||||
5044 | void | |||
5045 | trees_out::tree_vec (vec<tree, va_gc> *v) | |||
5046 | { | |||
5047 | unsigned len = vec_safe_length (v); | |||
5048 | if (streaming_p ()) | |||
5049 | u (len); | |||
5050 | for (unsigned ix = 0; ix != len; ix++) | |||
5051 | tree_node ((*v)[ix]); | |||
5052 | } | |||
5053 | ||||
5054 | vec<tree, va_gc> * | |||
5055 | trees_in::tree_vec () | |||
5056 | { | |||
5057 | vec<tree, va_gc> *v = NULLnullptr; | |||
5058 | if (unsigned len = u ()) | |||
5059 | { | |||
5060 | vec_alloc (v, len); | |||
5061 | for (unsigned ix = 0; ix != len; ix++) | |||
5062 | v->quick_push (tree_node ()); | |||
5063 | } | |||
5064 | return v; | |||
5065 | } | |||
5066 | ||||
5067 | /* A vector of tree pairs. */ | |||
5068 | ||||
5069 | void | |||
5070 | trees_out::tree_pair_vec (vec<tree_pair_s, va_gc> *v) | |||
5071 | { | |||
5072 | unsigned len = vec_safe_length (v); | |||
5073 | if (streaming_p ()) | |||
5074 | u (len); | |||
5075 | if (len) | |||
5076 | for (unsigned ix = 0; ix != len; ix++) | |||
5077 | { | |||
5078 | tree_pair_s const &s = (*v)[ix]; | |||
5079 | tree_node (s.purpose); | |||
5080 | tree_node (s.value); | |||
5081 | } | |||
5082 | } | |||
5083 | ||||
5084 | vec<tree_pair_s, va_gc> * | |||
5085 | trees_in::tree_pair_vec () | |||
5086 | { | |||
5087 | vec<tree_pair_s, va_gc> *v = NULLnullptr; | |||
5088 | if (unsigned len = u ()) | |||
5089 | { | |||
5090 | vec_alloc (v, len); | |||
5091 | for (unsigned ix = 0; ix != len; ix++) | |||
5092 | { | |||
5093 | tree_pair_s s; | |||
5094 | s.purpose = tree_node (); | |||
5095 | s.value = tree_node (); | |||
5096 | v->quick_push (s); | |||
5097 | } | |||
5098 | } | |||
5099 | return v; | |||
5100 | } | |||
5101 | ||||
5102 | void | |||
5103 | trees_out::tree_list (tree list, bool has_purpose) | |||
5104 | { | |||
5105 | for (; list; list = TREE_CHAIN (list)((contains_struct_check ((list), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5105, __FUNCTION__))->common.chain)) | |||
5106 | { | |||
5107 | gcc_checking_assert (TREE_VALUE (list))((void)(!(((tree_check ((list), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5107, __FUNCTION__, (TREE_LIST)))->list.value)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5107, __FUNCTION__), 0 : 0)); | |||
5108 | tree_node (TREE_VALUE (list)((tree_check ((list), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5108, __FUNCTION__, (TREE_LIST)))->list.value)); | |||
5109 | if (has_purpose) | |||
5110 | tree_node (TREE_PURPOSE (list)((tree_check ((list), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5110, __FUNCTION__, (TREE_LIST)))->list.purpose)); | |||
5111 | } | |||
5112 | tree_node (NULL_TREE(tree) nullptr); | |||
5113 | } | |||
5114 | ||||
5115 | tree | |||
5116 | trees_in::tree_list (bool has_purpose) | |||
5117 | { | |||
5118 | tree res = NULL_TREE(tree) nullptr; | |||
5119 | ||||
5120 | for (tree *chain = &res; tree value = tree_node (); | |||
5121 | chain = &TREE_CHAIN (*chain)((contains_struct_check ((*chain), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5121, __FUNCTION__))->common.chain)) | |||
5122 | { | |||
5123 | tree purpose = has_purpose ? tree_node () : NULL_TREE(tree) nullptr; | |||
5124 | *chain = build_tree_list (purpose, value); | |||
5125 | } | |||
5126 | ||||
5127 | return res; | |||
5128 | } | |||
5129 | /* Start tree write. Write information to allocate the receiving | |||
5130 | node. */ | |||
5131 | ||||
5132 | void | |||
5133 | trees_out::start (tree t, bool code_streamed) | |||
5134 | { | |||
5135 | if (TYPE_P (t)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (t)->base.code))] == tcc_type)) | |||
5136 | { | |||
5137 | enum tree_code code = TREE_CODE (t)((enum tree_code) (t)->base.code); | |||
5138 | gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t)((void)(!(((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5138, __FUNCTION__))->type_common.main_variant) == t) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5138, __FUNCTION__), 0 : 0)); | |||
5139 | /* All these types are TYPE_NON_COMMON. */ | |||
5140 | gcc_checking_assert (code == RECORD_TYPE((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)) | |||
5141 | || code == UNION_TYPE((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)) | |||
5142 | || code == ENUMERAL_TYPE((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)) | |||
5143 | || code == TEMPLATE_TYPE_PARM((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)) | |||
5144 | || code == TEMPLATE_TEMPLATE_PARM((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)) | |||
5145 | || code == BOUND_TEMPLATE_TEMPLATE_PARM)((void)(!(code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE || code == TEMPLATE_TYPE_PARM || code == TEMPLATE_TEMPLATE_PARM || code == BOUND_TEMPLATE_TEMPLATE_PARM) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5145, __FUNCTION__), 0 : 0)); | |||
5146 | } | |||
5147 | ||||
5148 | if (!code_streamed) | |||
5149 | u (TREE_CODE (t)((enum tree_code) (t)->base.code)); | |||
5150 | ||||
5151 | switch (TREE_CODE (t)((enum tree_code) (t)->base.code)) | |||
5152 | { | |||
5153 | default: | |||
5154 | if (TREE_CODE_CLASS (TREE_CODE (t))tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (t)->base.code))] == tcc_vl_exp) | |||
5155 | u (VL_EXP_OPERAND_LENGTH (t)((int)((unsigned long) (*tree_int_cst_elt_check (((tree_class_check ((t), (tcc_vl_exp), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5155, __FUNCTION__))->exp.operands[0]), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5155, __FUNCTION__))))); | |||
5156 | break; | |||
5157 | ||||
5158 | case INTEGER_CST: | |||
5159 | u (TREE_INT_CST_NUNITS (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5159, __FUNCTION__, (INTEGER_CST)))->base.u.int_length.unextended )); | |||
5160 | u (TREE_INT_CST_EXT_NUNITS (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5160, __FUNCTION__, (INTEGER_CST)))->base.u.int_length.extended )); | |||
5161 | u (TREE_INT_CST_OFFSET_NUNITS (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5161, __FUNCTION__, (INTEGER_CST)))->base.u.int_length.offset )); | |||
5162 | break; | |||
5163 | ||||
5164 | case OMP_CLAUSE: | |||
5165 | state->extensions |= SE_OPENMP; | |||
5166 | u (OMP_CLAUSE_CODE (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5166, __FUNCTION__, (OMP_CLAUSE))))->omp_clause.code); | |||
5167 | break; | |||
5168 | ||||
5169 | case STRING_CST: | |||
5170 | str (TREE_STRING_POINTER (t)((const char *)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5170, __FUNCTION__, (STRING_CST)))->string.str)), TREE_STRING_LENGTH (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5170, __FUNCTION__, (STRING_CST)))->string.length)); | |||
5171 | break; | |||
5172 | ||||
5173 | case VECTOR_CST: | |||
5174 | u (VECTOR_CST_LOG2_NPATTERNS (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5174, __FUNCTION__, (VECTOR_CST)))->base.u.vector_cst.log2_npatterns )); | |||
5175 | u (VECTOR_CST_NELTS_PER_PATTERN (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5175, __FUNCTION__, (VECTOR_CST)))->base.u.vector_cst.nelts_per_pattern )); | |||
5176 | break; | |||
5177 | ||||
5178 | case TREE_BINFO: | |||
5179 | u (BINFO_N_BASE_BINFOS (t)((&(tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5179, __FUNCTION__, (TREE_BINFO)))->binfo.base_binfos)-> length ())); | |||
5180 | break; | |||
5181 | ||||
5182 | case TREE_VEC: | |||
5183 | u (TREE_VEC_LENGTH (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5183, __FUNCTION__, (TREE_VEC)))->base.u.length)); | |||
5184 | break; | |||
5185 | ||||
5186 | case FIXED_CST: | |||
5187 | case POLY_INT_CST: | |||
5188 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5188, __FUNCTION__)); /* Not supported in C++. */ | |||
5189 | break; | |||
5190 | ||||
5191 | case IDENTIFIER_NODE: | |||
5192 | case SSA_NAME: | |||
5193 | case TARGET_MEM_REF: | |||
5194 | case TRANSLATION_UNIT_DECL: | |||
5195 | /* We shouldn't meet these. */ | |||
5196 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5196, __FUNCTION__)); | |||
5197 | break; | |||
5198 | } | |||
5199 | } | |||
5200 | ||||
5201 | /* Start tree read. Allocate the receiving node. */ | |||
5202 | ||||
5203 | tree | |||
5204 | trees_in::start (unsigned code) | |||
5205 | { | |||
5206 | tree t = NULL_TREE(tree) nullptr; | |||
5207 | ||||
5208 | if (!code) | |||
5209 | code = u (); | |||
5210 | ||||
5211 | switch (code) | |||
5212 | { | |||
5213 | default: | |||
5214 | if (code >= MAX_TREE_CODES) | |||
5215 | { | |||
5216 | fail: | |||
5217 | set_overrun (); | |||
5218 | return NULL_TREE(tree) nullptr; | |||
5219 | } | |||
5220 | else if (TREE_CODE_CLASS (code)tree_code_type_tmpl <0>::tree_code_type[(int) (code)] == tcc_vl_exp) | |||
5221 | { | |||
5222 | unsigned ops = u (); | |||
5223 | t = build_vl_exp (tree_code (code), ops); | |||
5224 | } | |||
5225 | else | |||
5226 | t = make_node (tree_code (code)); | |||
5227 | break; | |||
5228 | ||||
5229 | case INTEGER_CST: | |||
5230 | { | |||
5231 | unsigned n = u (); | |||
5232 | unsigned e = u (); | |||
5233 | t = make_int_cst (n, e); | |||
5234 | TREE_INT_CST_OFFSET_NUNITS(t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5234, __FUNCTION__, (INTEGER_CST)))->base.u.int_length.offset ) = u (); | |||
5235 | } | |||
5236 | break; | |||
5237 | ||||
5238 | case OMP_CLAUSE: | |||
5239 | { | |||
5240 | if (!(state->extensions & SE_OPENMP)) | |||
5241 | goto fail; | |||
5242 | ||||
5243 | unsigned omp_code = u (); | |||
5244 | t = build_omp_clause (UNKNOWN_LOCATION((location_t) 0), omp_clause_code (omp_code)); | |||
5245 | } | |||
5246 | break; | |||
5247 | ||||
5248 | case STRING_CST: | |||
5249 | { | |||
5250 | size_t l; | |||
5251 | const char *chars = str (&l); | |||
5252 | t = build_string (l, chars); | |||
5253 | } | |||
5254 | break; | |||
5255 | ||||
5256 | case VECTOR_CST: | |||
5257 | { | |||
5258 | unsigned log2_npats = u (); | |||
5259 | unsigned elts_per = u (); | |||
5260 | t = make_vector (log2_npats, elts_per); | |||
5261 | } | |||
5262 | break; | |||
5263 | ||||
5264 | case TREE_BINFO: | |||
5265 | t = make_tree_binfo (u ()); | |||
5266 | break; | |||
5267 | ||||
5268 | case TREE_VEC: | |||
5269 | t = make_tree_vec (u ()); | |||
5270 | break; | |||
5271 | ||||
5272 | case FIXED_CST: | |||
5273 | case IDENTIFIER_NODE: | |||
5274 | case POLY_INT_CST: | |||
5275 | case SSA_NAME: | |||
5276 | case TARGET_MEM_REF: | |||
5277 | case TRANSLATION_UNIT_DECL: | |||
5278 | goto fail; | |||
5279 | } | |||
5280 | ||||
5281 | return t; | |||
5282 | } | |||
5283 | ||||
5284 | /* The structure streamers access the raw fields, because the | |||
5285 | alternative, of using the accessor macros can require using | |||
5286 | different accessors for the same underlying field, depending on the | |||
5287 | tree code. That's both confusing and annoying. */ | |||
5288 | ||||
5289 | /* Read & write the core boolean flags. */ | |||
5290 | ||||
5291 | void | |||
5292 | trees_out::core_bools (tree t) | |||
5293 | { | |||
5294 | #define WB(X) (b (X)) | |||
5295 | tree_code code = TREE_CODE (t)((enum tree_code) (t)->base.code); | |||
5296 | ||||
5297 | WB (t->base.side_effects_flag); | |||
5298 | WB (t->base.constant_flag); | |||
5299 | WB (t->base.addressable_flag); | |||
5300 | WB (t->base.volatile_flag); | |||
5301 | WB (t->base.readonly_flag); | |||
5302 | /* base.asm_written_flag is a property of the current TU's use of | |||
5303 | this decl. */ | |||
5304 | WB (t->base.nowarning_flag); | |||
5305 | /* base.visited read as zero (it's set for writer, because that's | |||
5306 | how we mark nodes). */ | |||
5307 | /* base.used_flag is not streamed. Readers may set TREE_USED of | |||
5308 | decls they use. */ | |||
5309 | WB (t->base.nothrow_flag); | |||
5310 | WB (t->base.static_flag); | |||
5311 | if (TREE_CODE_CLASS (code)tree_code_type_tmpl <0>::tree_code_type[(int) (code)] != tcc_type) | |||
5312 | /* This is TYPE_CACHED_VALUES_P for types. */ | |||
5313 | WB (t->base.public_flag); | |||
5314 | WB (t->base.private_flag); | |||
5315 | WB (t->base.protected_flag); | |||
5316 | WB (t->base.deprecated_flag); | |||
5317 | WB (t->base.default_def_flag); | |||
5318 | ||||
5319 | switch (code) | |||
5320 | { | |||
5321 | case CALL_EXPR: | |||
5322 | case INTEGER_CST: | |||
5323 | case SSA_NAME: | |||
5324 | case TARGET_MEM_REF: | |||
5325 | case TREE_VEC: | |||
5326 | /* These use different base.u fields. */ | |||
5327 | break; | |||
5328 | ||||
5329 | default: | |||
5330 | WB (t->base.u.bits.lang_flag_0); | |||
5331 | bool flag_1 = t->base.u.bits.lang_flag_1; | |||
5332 | if (!flag_1) | |||
5333 | ; | |||
5334 | else if (code == TEMPLATE_INFO) | |||
5335 | /* This is TI_PENDING_TEMPLATE_FLAG, not relevant to reader. */ | |||
5336 | flag_1 = false; | |||
5337 | else if (code == VAR_DECL) | |||
5338 | { | |||
5339 | /* This is DECL_INITIALIZED_P. */ | |||
5340 | if (TREE_CODE (DECL_CONTEXT (t))((enum tree_code) (((contains_struct_check ((t), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5340, __FUNCTION__))->decl_minimal.context))->base.code ) != FUNCTION_DECL) | |||
5341 | /* We'll set this when reading the definition. */ | |||
5342 | flag_1 = false; | |||
5343 | } | |||
5344 | WB (flag_1); | |||
5345 | WB (t->base.u.bits.lang_flag_2); | |||
5346 | WB (t->base.u.bits.lang_flag_3); | |||
5347 | WB (t->base.u.bits.lang_flag_4); | |||
5348 | WB (t->base.u.bits.lang_flag_5); | |||
5349 | WB (t->base.u.bits.lang_flag_6); | |||
5350 | WB (t->base.u.bits.saturating_flag); | |||
5351 | WB (t->base.u.bits.unsigned_flag); | |||
5352 | WB (t->base.u.bits.packed_flag); | |||
5353 | WB (t->base.u.bits.user_align); | |||
5354 | WB (t->base.u.bits.nameless_flag); | |||
5355 | WB (t->base.u.bits.atomic_flag); | |||
5356 | break; | |||
5357 | } | |||
5358 | ||||
5359 | if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)(tree_contains_struct[(code)][(TS_TYPE_COMMON)])) | |||
5360 | { | |||
5361 | WB (t->type_common.no_force_blk_flag); | |||
5362 | WB (t->type_common.needs_constructing_flag); | |||
5363 | WB (t->type_common.transparent_aggr_flag); | |||
5364 | WB (t->type_common.restrict_flag); | |||
5365 | WB (t->type_common.string_flag); | |||
5366 | WB (t->type_common.lang_flag_0); | |||
5367 | WB (t->type_common.lang_flag_1); | |||
5368 | WB (t->type_common.lang_flag_2); | |||
5369 | WB (t->type_common.lang_flag_3); | |||
5370 | WB (t->type_common.lang_flag_4); | |||
5371 | WB (t->type_common.lang_flag_5); | |||
5372 | WB (t->type_common.lang_flag_6); | |||
5373 | WB (t->type_common.typeless_storage); | |||
5374 | } | |||
5375 | ||||
5376 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)(tree_contains_struct[(code)][(TS_DECL_COMMON)])) | |||
5377 | { | |||
5378 | WB (t->decl_common.nonlocal_flag); | |||
5379 | WB (t->decl_common.virtual_flag); | |||
5380 | WB (t->decl_common.ignored_flag); | |||
5381 | WB (t->decl_common.abstract_flag); | |||
5382 | WB (t->decl_common.artificial_flag); | |||
5383 | WB (t->decl_common.preserve_flag); | |||
5384 | WB (t->decl_common.debug_expr_is_from); | |||
5385 | WB (t->decl_common.lang_flag_0); | |||
5386 | WB (t->decl_common.lang_flag_1); | |||
5387 | WB (t->decl_common.lang_flag_2); | |||
5388 | WB (t->decl_common.lang_flag_3); | |||
5389 | WB (t->decl_common.lang_flag_4); | |||
5390 | WB (t->decl_common.lang_flag_5); | |||
5391 | WB (t->decl_common.lang_flag_6); | |||
5392 | WB (t->decl_common.lang_flag_7); | |||
5393 | WB (t->decl_common.lang_flag_8); | |||
5394 | WB (t->decl_common.decl_flag_0); | |||
5395 | ||||
5396 | { | |||
5397 | /* DECL_EXTERNAL -> decl_flag_1 | |||
5398 | == it is defined elsewhere | |||
5399 | DECL_NOT_REALLY_EXTERN -> base.not_really_extern | |||
5400 | == that was a lie, it is here */ | |||
5401 | ||||
5402 | bool is_external = t->decl_common.decl_flag_1; | |||
5403 | if (!is_external) | |||
5404 | /* decl_flag_1 is DECL_EXTERNAL. Things we emit here, might | |||
5405 | well be external from the POV of an importer. */ | |||
5406 | // FIXME: Do we need to know if this is a TEMPLATE_RESULT -- | |||
5407 | // a flag from the caller? | |||
5408 | switch (code) | |||
5409 | { | |||
5410 | default: | |||
5411 | break; | |||
5412 | ||||
5413 | case VAR_DECL: | |||
5414 | if (TREE_PUBLIC (t)((t)->base.public_flag) | |||
5415 | && !(TREE_STATIC (t)((t)->base.static_flag) | |||
5416 | && DECL_FUNCTION_SCOPE_P (t)(((contains_struct_check ((t), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5416, __FUNCTION__))->decl_minimal.context) && ( (enum tree_code) (((contains_struct_check ((t), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5416, __FUNCTION__))->decl_minimal.context))->base.code ) == FUNCTION_DECL) | |||
5417 | && DECL_DECLARED_INLINE_P (DECL_CONTEXT (t))((tree_check ((((contains_struct_check ((t), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5417, __FUNCTION__))->decl_minimal.context)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5417, __FUNCTION__, (FUNCTION_DECL)))->function_decl.declared_inline_flag )) | |||
5418 | && !DECL_VAR_DECLARED_INLINE_P (t)(((contains_struct_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5418, __FUNCTION__, (VAR_DECL)))), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5418, __FUNCTION__))->decl_common.lang_specific) ? ((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5418, __FUNCTION__))->decl_common.lang_specific)->u.base .var_declared_inline_p : false)) | |||
5419 | is_external = true; | |||
5420 | break; | |||
5421 | ||||
5422 | case FUNCTION_DECL: | |||
5423 | if (TREE_PUBLIC (t)((t)->base.public_flag) | |||
5424 | && !DECL_DECLARED_INLINE_P (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5424, __FUNCTION__, (FUNCTION_DECL)))->function_decl.declared_inline_flag )) | |||
5425 | is_external = true; | |||
5426 | break; | |||
5427 | } | |||
5428 | WB (is_external); | |||
5429 | } | |||
5430 | ||||
5431 | WB (t->decl_common.decl_flag_2); | |||
5432 | WB (t->decl_common.decl_flag_3); | |||
5433 | WB (t->decl_common.not_gimple_reg_flag); | |||
5434 | WB (t->decl_common.decl_by_reference_flag); | |||
5435 | WB (t->decl_common.decl_read_flag); | |||
5436 | WB (t->decl_common.decl_nonshareable_flag); | |||
5437 | WB (t->decl_common.decl_not_flexarray); | |||
5438 | } | |||
5439 | ||||
5440 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)(tree_contains_struct[(code)][(TS_DECL_WITH_VIS)])) | |||
5441 | { | |||
5442 | WB (t->decl_with_vis.defer_output); | |||
5443 | WB (t->decl_with_vis.hard_register); | |||
5444 | WB (t->decl_with_vis.common_flag); | |||
5445 | WB (t->decl_with_vis.in_text_section); | |||
5446 | WB (t->decl_with_vis.in_constant_pool); | |||
5447 | WB (t->decl_with_vis.dllimport_flag); | |||
5448 | WB (t->decl_with_vis.weak_flag); | |||
5449 | WB (t->decl_with_vis.seen_in_bind_expr); | |||
5450 | WB (t->decl_with_vis.comdat_flag); | |||
5451 | WB (t->decl_with_vis.visibility_specified); | |||
5452 | WB (t->decl_with_vis.init_priority_p); | |||
5453 | WB (t->decl_with_vis.shadowed_for_var_p); | |||
5454 | WB (t->decl_with_vis.cxx_constructor); | |||
5455 | WB (t->decl_with_vis.cxx_destructor); | |||
5456 | WB (t->decl_with_vis.final); | |||
5457 | WB (t->decl_with_vis.regdecl_flag); | |||
5458 | } | |||
5459 | ||||
5460 | if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)(tree_contains_struct[(code)][(TS_FUNCTION_DECL)])) | |||
5461 | { | |||
5462 | WB (t->function_decl.static_ctor_flag); | |||
5463 | WB (t->function_decl.static_dtor_flag); | |||
5464 | WB (t->function_decl.uninlinable); | |||
5465 | WB (t->function_decl.possibly_inlined); | |||
5466 | WB (t->function_decl.novops_flag); | |||
5467 | WB (t->function_decl.returns_twice_flag); | |||
5468 | WB (t->function_decl.malloc_flag); | |||
5469 | WB (t->function_decl.declared_inline_flag); | |||
5470 | WB (t->function_decl.no_inline_warning_flag); | |||
5471 | WB (t->function_decl.no_instrument_function_entry_exit); | |||
5472 | WB (t->function_decl.no_limit_stack); | |||
5473 | WB (t->function_decl.disregard_inline_limits); | |||
5474 | WB (t->function_decl.pure_flag); | |||
5475 | WB (t->function_decl.looping_const_or_pure_flag); | |||
5476 | ||||
5477 | WB (t->function_decl.has_debug_args_flag); | |||
5478 | WB (t->function_decl.versioned_function); | |||
5479 | ||||
5480 | /* decl_type is a (misnamed) 2 bit discriminator. */ | |||
5481 | unsigned kind = t->function_decl.decl_type; | |||
5482 | WB ((kind >> 0) & 1); | |||
5483 | WB ((kind >> 1) & 1); | |||
5484 | } | |||
5485 | #undef WB | |||
5486 | } | |||
5487 | ||||
5488 | bool | |||
5489 | trees_in::core_bools (tree t) | |||
5490 | { | |||
5491 | #define RB(X) ((X) = b ()) | |||
5492 | tree_code code = TREE_CODE (t)((enum tree_code) (t)->base.code); | |||
5493 | ||||
5494 | RB (t->base.side_effects_flag); | |||
5495 | RB (t->base.constant_flag); | |||
5496 | RB (t->base.addressable_flag); | |||
5497 | RB (t->base.volatile_flag); | |||
5498 | RB (t->base.readonly_flag); | |||
5499 | /* base.asm_written_flag is not streamed. */ | |||
5500 | RB (t->base.nowarning_flag); | |||
5501 | /* base.visited is not streamed. */ | |||
5502 | /* base.used_flag is not streamed. */ | |||
5503 | RB (t->base.nothrow_flag); | |||
5504 | RB (t->base.static_flag); | |||
5505 | if (TREE_CODE_CLASS (code)tree_code_type_tmpl <0>::tree_code_type[(int) (code)] != tcc_type) | |||
5506 | RB (t->base.public_flag); | |||
5507 | RB (t->base.private_flag); | |||
5508 | RB (t->base.protected_flag); | |||
5509 | RB (t->base.deprecated_flag); | |||
5510 | RB (t->base.default_def_flag); | |||
5511 | ||||
5512 | switch (code) | |||
5513 | { | |||
5514 | case CALL_EXPR: | |||
5515 | case INTEGER_CST: | |||
5516 | case SSA_NAME: | |||
5517 | case TARGET_MEM_REF: | |||
5518 | case TREE_VEC: | |||
5519 | /* These use different base.u fields. */ | |||
5520 | break; | |||
5521 | ||||
5522 | default: | |||
5523 | RB (t->base.u.bits.lang_flag_0); | |||
5524 | RB (t->base.u.bits.lang_flag_1); | |||
5525 | RB (t->base.u.bits.lang_flag_2); | |||
5526 | RB (t->base.u.bits.lang_flag_3); | |||
5527 | RB (t->base.u.bits.lang_flag_4); | |||
5528 | RB (t->base.u.bits.lang_flag_5); | |||
5529 | RB (t->base.u.bits.lang_flag_6); | |||
5530 | RB (t->base.u.bits.saturating_flag); | |||
5531 | RB (t->base.u.bits.unsigned_flag); | |||
5532 | RB (t->base.u.bits.packed_flag); | |||
5533 | RB (t->base.u.bits.user_align); | |||
5534 | RB (t->base.u.bits.nameless_flag); | |||
5535 | RB (t->base.u.bits.atomic_flag); | |||
5536 | break; | |||
5537 | } | |||
5538 | ||||
5539 | if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)(tree_contains_struct[(code)][(TS_TYPE_COMMON)])) | |||
5540 | { | |||
5541 | RB (t->type_common.no_force_blk_flag); | |||
5542 | RB (t->type_common.needs_constructing_flag); | |||
5543 | RB (t->type_common.transparent_aggr_flag); | |||
5544 | RB (t->type_common.restrict_flag); | |||
5545 | RB (t->type_common.string_flag); | |||
5546 | RB (t->type_common.lang_flag_0); | |||
5547 | RB (t->type_common.lang_flag_1); | |||
5548 | RB (t->type_common.lang_flag_2); | |||
5549 | RB (t->type_common.lang_flag_3); | |||
5550 | RB (t->type_common.lang_flag_4); | |||
5551 | RB (t->type_common.lang_flag_5); | |||
5552 | RB (t->type_common.lang_flag_6); | |||
5553 | RB (t->type_common.typeless_storage); | |||
5554 | } | |||
5555 | ||||
5556 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)(tree_contains_struct[(code)][(TS_DECL_COMMON)])) | |||
5557 | { | |||
5558 | RB (t->decl_common.nonlocal_flag); | |||
5559 | RB (t->decl_common.virtual_flag); | |||
5560 | RB (t->decl_common.ignored_flag); | |||
5561 | RB (t->decl_common.abstract_flag); | |||
5562 | RB (t->decl_common.artificial_flag); | |||
5563 | RB (t->decl_common.preserve_flag); | |||
5564 | RB (t->decl_common.debug_expr_is_from); | |||
5565 | RB (t->decl_common.lang_flag_0); | |||
5566 | RB (t->decl_common.lang_flag_1); | |||
5567 | RB (t->decl_common.lang_flag_2); | |||
5568 | RB (t->decl_common.lang_flag_3); | |||
5569 | RB (t->decl_common.lang_flag_4); | |||
5570 | RB (t->decl_common.lang_flag_5); | |||
5571 | RB (t->decl_common.lang_flag_6); | |||
5572 | RB (t->decl_common.lang_flag_7); | |||
5573 | RB (t->decl_common.lang_flag_8); | |||
5574 | RB (t->decl_common.decl_flag_0); | |||
5575 | RB (t->decl_common.decl_flag_1); | |||
5576 | RB (t->decl_common.decl_flag_2); | |||
5577 | RB (t->decl_common.decl_flag_3); | |||
5578 | RB (t->decl_common.not_gimple_reg_flag); | |||
5579 | RB (t->decl_common.decl_by_reference_flag); | |||
5580 | RB (t->decl_common.decl_read_flag); | |||
5581 | RB (t->decl_common.decl_nonshareable_flag); | |||
5582 | RB (t->decl_common.decl_not_flexarray); | |||
5583 | } | |||
5584 | ||||
5585 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)(tree_contains_struct[(code)][(TS_DECL_WITH_VIS)])) | |||
5586 | { | |||
5587 | RB (t->decl_with_vis.defer_output); | |||
5588 | RB (t->decl_with_vis.hard_register); | |||
5589 | RB (t->decl_with_vis.common_flag); | |||
5590 | RB (t->decl_with_vis.in_text_section); | |||
5591 | RB (t->decl_with_vis.in_constant_pool); | |||
5592 | RB (t->decl_with_vis.dllimport_flag); | |||
5593 | RB (t->decl_with_vis.weak_flag); | |||
5594 | RB (t->decl_with_vis.seen_in_bind_expr); | |||
5595 | RB (t->decl_with_vis.comdat_flag); | |||
5596 | RB (t->decl_with_vis.visibility_specified); | |||
5597 | RB (t->decl_with_vis.init_priority_p); | |||
5598 | RB (t->decl_with_vis.shadowed_for_var_p); | |||
5599 | RB (t->decl_with_vis.cxx_constructor); | |||
5600 | RB (t->decl_with_vis.cxx_destructor); | |||
5601 | RB (t->decl_with_vis.final); | |||
5602 | RB (t->decl_with_vis.regdecl_flag); | |||
5603 | } | |||
5604 | ||||
5605 | if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)(tree_contains_struct[(code)][(TS_FUNCTION_DECL)])) | |||
5606 | { | |||
5607 | RB (t->function_decl.static_ctor_flag); | |||
5608 | RB (t->function_decl.static_dtor_flag); | |||
5609 | RB (t->function_decl.uninlinable); | |||
5610 | RB (t->function_decl.possibly_inlined); | |||
5611 | RB (t->function_decl.novops_flag); | |||
5612 | RB (t->function_decl.returns_twice_flag); | |||
5613 | RB (t->function_decl.malloc_flag); | |||
5614 | RB (t->function_decl.declared_inline_flag); | |||
5615 | RB (t->function_decl.no_inline_warning_flag); | |||
5616 | RB (t->function_decl.no_instrument_function_entry_exit); | |||
5617 | RB (t->function_decl.no_limit_stack); | |||
5618 | RB (t->function_decl.disregard_inline_limits); | |||
5619 | RB (t->function_decl.pure_flag); | |||
5620 | RB (t->function_decl.looping_const_or_pure_flag); | |||
5621 | ||||
5622 | RB (t->function_decl.has_debug_args_flag); | |||
5623 | RB (t->function_decl.versioned_function); | |||
5624 | ||||
5625 | /* decl_type is a (misnamed) 2 bit discriminator. */ | |||
5626 | unsigned kind = 0; | |||
5627 | kind |= unsigned (b ()) << 0; | |||
5628 | kind |= unsigned (b ()) << 1; | |||
5629 | t->function_decl.decl_type = function_decl_type (kind); | |||
5630 | } | |||
5631 | #undef RB | |||
5632 | return !get_overrun (); | |||
5633 | } | |||
5634 | ||||
5635 | void | |||
5636 | trees_out::lang_decl_bools (tree t) | |||
5637 | { | |||
5638 | #define WB(X) (b (X)) | |||
5639 | const struct lang_decl *lang = DECL_LANG_SPECIFIC (t)((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5639, __FUNCTION__))->decl_common.lang_specific); | |||
5640 | ||||
5641 | WB (lang->u.base.language == lang_cplusplus); | |||
| ||||
5642 | WB ((lang->u.base.use_template >> 0) & 1); | |||
5643 | WB ((lang->u.base.use_template >> 1) & 1); | |||
5644 | /* Do not write lang->u.base.not_really_extern, importer will set | |||
5645 | when reading the definition (if any). */ | |||
5646 | WB (lang->u.base.initialized_in_class); | |||
5647 | WB (lang->u.base.threadprivate_or_deleted_p); | |||
5648 | /* Do not write lang->u.base.anticipated_p, it is a property of the | |||
5649 | current TU. */ | |||
5650 | WB (lang->u.base.friend_or_tls); | |||
5651 | WB (lang->u.base.unknown_bound_p); | |||
5652 | /* Do not write lang->u.base.odr_used, importer will recalculate if | |||
5653 | they do ODR use this decl. */ | |||
5654 | WB (lang->u.base.concept_p); | |||
5655 | WB (lang->u.base.var_declared_inline_p); | |||
5656 | WB (lang->u.base.dependent_init_p); | |||
5657 | /* When building a header unit, everthing is marked as purview, (so | |||
5658 | we know which decls to write). But when we import them we do not | |||
5659 | want to mark them as in module purview. */ | |||
5660 | WB (lang->u.base.module_purview_p && !header_module_p ()); | |||
5661 | WB (lang->u.base.module_attach_p); | |||
5662 | if (VAR_OR_FUNCTION_DECL_P (t)(((enum tree_code) (t)->base.code) == VAR_DECL || ((enum tree_code ) (t)->base.code) == FUNCTION_DECL)) | |||
5663 | WB (lang->u.base.module_keyed_decls_p); | |||
5664 | switch (lang->u.base.selector) | |||
5665 | { | |||
5666 | default: | |||
5667 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5667, __FUNCTION__)); | |||
5668 | ||||
5669 | case lds_fn: /* lang_decl_fn. */ | |||
5670 | WB (lang->u.fn.global_ctor_p); | |||
5671 | WB (lang->u.fn.global_dtor_p); | |||
5672 | WB (lang->u.fn.static_function); | |||
5673 | WB (lang->u.fn.pure_virtual); | |||
5674 | WB (lang->u.fn.defaulted_p); | |||
5675 | WB (lang->u.fn.has_in_charge_parm_p); | |||
5676 | WB (lang->u.fn.has_vtt_parm_p); | |||
5677 | /* There shouldn't be a pending inline at this point. */ | |||
5678 | gcc_assert (!lang->u.fn.pending_inline_p)((void)(!(!lang->u.fn.pending_inline_p) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5678, __FUNCTION__), 0 : 0)); | |||
5679 | WB (lang->u.fn.nonconverting); | |||
5680 | WB (lang->u.fn.thunk_p); | |||
5681 | WB (lang->u.fn.this_thunk_p); | |||
5682 | /* Do not stream lang->u.hidden_friend_p, it is a property of | |||
5683 | the TU. */ | |||
5684 | WB (lang->u.fn.omp_declare_reduction_p); | |||
5685 | WB (lang->u.fn.has_dependent_explicit_spec_p); | |||
5686 | WB (lang->u.fn.immediate_fn_p); | |||
5687 | WB (lang->u.fn.maybe_deleted); | |||
5688 | goto lds_min; | |||
5689 | ||||
5690 | case lds_decomp: /* lang_decl_decomp. */ | |||
5691 | /* No bools. */ | |||
5692 | goto lds_min; | |||
5693 | ||||
5694 | case lds_min: /* lang_decl_min. */ | |||
5695 | lds_min: | |||
5696 | /* No bools. */ | |||
5697 | break; | |||
5698 | ||||
5699 | case lds_ns: /* lang_decl_ns. */ | |||
5700 | /* No bools. */ | |||
5701 | break; | |||
5702 | ||||
5703 | case lds_parm: /* lang_decl_parm. */ | |||
5704 | /* No bools. */ | |||
5705 | break; | |||
5706 | } | |||
5707 | #undef WB | |||
5708 | } | |||
5709 | ||||
5710 | bool | |||
5711 | trees_in::lang_decl_bools (tree t) | |||
5712 | { | |||
5713 | #define RB(X) ((X) = b ()) | |||
5714 | struct lang_decl *lang = DECL_LANG_SPECIFIC (t)((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5714, __FUNCTION__))->decl_common.lang_specific); | |||
5715 | ||||
5716 | lang->u.base.language = b () ? lang_cplusplus : lang_c; | |||
5717 | unsigned v; | |||
5718 | v = b () << 0; | |||
5719 | v |= b () << 1; | |||
5720 | lang->u.base.use_template = v; | |||
5721 | /* lang->u.base.not_really_extern is not streamed. */ | |||
5722 | RB (lang->u.base.initialized_in_class); | |||
5723 | RB (lang->u.base.threadprivate_or_deleted_p); | |||
5724 | /* lang->u.base.anticipated_p is not streamed. */ | |||
5725 | RB (lang->u.base.friend_or_tls); | |||
5726 | RB (lang->u.base.unknown_bound_p); | |||
5727 | /* lang->u.base.odr_used is not streamed. */ | |||
5728 | RB (lang->u.base.concept_p); | |||
5729 | RB (lang->u.base.var_declared_inline_p); | |||
5730 | RB (lang->u.base.dependent_init_p); | |||
5731 | RB (lang->u.base.module_purview_p); | |||
5732 | RB (lang->u.base.module_attach_p); | |||
5733 | if (VAR_OR_FUNCTION_DECL_P (t)(((enum tree_code) (t)->base.code) == VAR_DECL || ((enum tree_code ) (t)->base.code) == FUNCTION_DECL)) | |||
5734 | RB (lang->u.base.module_keyed_decls_p); | |||
5735 | switch (lang->u.base.selector) | |||
5736 | { | |||
5737 | default: | |||
5738 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5738, __FUNCTION__)); | |||
5739 | ||||
5740 | case lds_fn: /* lang_decl_fn. */ | |||
5741 | RB (lang->u.fn.global_ctor_p); | |||
5742 | RB (lang->u.fn.global_dtor_p); | |||
5743 | RB (lang->u.fn.static_function); | |||
5744 | RB (lang->u.fn.pure_virtual); | |||
5745 | RB (lang->u.fn.defaulted_p); | |||
5746 | RB (lang->u.fn.has_in_charge_parm_p); | |||
5747 | RB (lang->u.fn.has_vtt_parm_p); | |||
5748 | RB (lang->u.fn.nonconverting); | |||
5749 | RB (lang->u.fn.thunk_p); | |||
5750 | RB (lang->u.fn.this_thunk_p); | |||
5751 | /* lang->u.fn.hidden_friend_p is not streamed. */ | |||
5752 | RB (lang->u.fn.omp_declare_reduction_p); | |||
5753 | RB (lang->u.fn.has_dependent_explicit_spec_p); | |||
5754 | RB (lang->u.fn.immediate_fn_p); | |||
5755 | RB (lang->u.fn.maybe_deleted); | |||
5756 | goto lds_min; | |||
5757 | ||||
5758 | case lds_decomp: /* lang_decl_decomp. */ | |||
5759 | /* No bools. */ | |||
5760 | goto lds_min; | |||
5761 | ||||
5762 | case lds_min: /* lang_decl_min. */ | |||
5763 | lds_min: | |||
5764 | /* No bools. */ | |||
5765 | break; | |||
5766 | ||||
5767 | case lds_ns: /* lang_decl_ns. */ | |||
5768 | /* No bools. */ | |||
5769 | break; | |||
5770 | ||||
5771 | case lds_parm: /* lang_decl_parm. */ | |||
5772 | /* No bools. */ | |||
5773 | break; | |||
5774 | } | |||
5775 | #undef RB | |||
5776 | return !get_overrun (); | |||
5777 | } | |||
5778 | ||||
5779 | void | |||
5780 | trees_out::lang_type_bools (tree t) | |||
5781 | { | |||
5782 | #define WB(X) (b (X)) | |||
5783 | const struct lang_type *lang = TYPE_LANG_SPECIFIC (t)((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5783, __FUNCTION__))->type_with_lang_specific.lang_specific ); | |||
5784 | ||||
5785 | WB (lang->has_type_conversion); | |||
5786 | WB (lang->has_copy_ctor); | |||
5787 | WB (lang->has_default_ctor); | |||
5788 | WB (lang->const_needs_init); | |||
5789 | WB (lang->ref_needs_init); | |||
5790 | WB (lang->has_const_copy_assign); | |||
5791 | WB ((lang->use_template >> 0) & 1); | |||
5792 | WB ((lang->use_template >> 1) & 1); | |||
5793 | ||||
5794 | WB (lang->has_mutable); | |||
5795 | WB (lang->com_interface); | |||
5796 | WB (lang->non_pod_class); | |||
5797 | WB (lang->nearly_empty_p); | |||
5798 | WB (lang->user_align); | |||
5799 | WB (lang->has_copy_assign); | |||
5800 | WB (lang->has_new); | |||
5801 | WB (lang->has_array_new); | |||
5802 | ||||
5803 | WB ((lang->gets_delete >> 0) & 1); | |||
5804 | WB ((lang->gets_delete >> 1) & 1); | |||
5805 | // Interfaceness is recalculated upon reading. May have to revisit? | |||
5806 | // How do dllexport and dllimport interact across a module? | |||
5807 | // lang->interface_only | |||
5808 | // lang->interface_unknown | |||
5809 | WB (lang->contains_empty_class_p); | |||
5810 | WB (lang->anon_aggr); | |||
5811 | WB (lang->non_zero_init); | |||
5812 | WB (lang->empty_p); | |||
5813 | ||||
5814 | WB (lang->vec_new_uses_cookie); | |||
5815 | WB (lang->declared_class); | |||
5816 | WB (lang->diamond_shaped); | |||
5817 | WB (lang->repeated_base); | |||
5818 | gcc_assert (!lang->being_defined)((void)(!(!lang->being_defined) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5818, __FUNCTION__), 0 : 0)); | |||
5819 | // lang->debug_requested | |||
5820 | WB (lang->fields_readonly); | |||
5821 | WB (lang->ptrmemfunc_flag); | |||
5822 | ||||
5823 | WB (lang->lazy_default_ctor); | |||
5824 | WB (lang->lazy_copy_ctor); | |||
5825 | WB (lang->lazy_copy_assign); | |||
5826 | WB (lang->lazy_destructor); | |||
5827 | WB (lang->has_const_copy_ctor); | |||
5828 | WB (lang->has_complex_copy_ctor); | |||
5829 | WB (lang->has_complex_copy_assign); | |||
5830 | WB (lang->non_aggregate); | |||
5831 | ||||
5832 | WB (lang->has_complex_dflt); | |||
5833 | WB (lang->has_list_ctor); | |||
5834 | WB (lang->non_std_layout); | |||
5835 | WB (lang->is_literal); | |||
5836 | WB (lang->lazy_move_ctor); | |||
5837 | WB (lang->lazy_move_assign); | |||
5838 | WB (lang->has_complex_move_ctor); | |||
5839 | WB (lang->has_complex_move_assign); | |||
5840 | ||||
5841 | WB (lang->has_constexpr_ctor); | |||
5842 | WB (lang->unique_obj_representations); | |||
5843 | WB (lang->unique_obj_representations_set); | |||
5844 | #undef WB | |||
5845 | } | |||
5846 | ||||
5847 | bool | |||
5848 | trees_in::lang_type_bools (tree t) | |||
5849 | { | |||
5850 | #define RB(X) ((X) = b ()) | |||
5851 | struct lang_type *lang = TYPE_LANG_SPECIFIC (t)((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5851, __FUNCTION__))->type_with_lang_specific.lang_specific ); | |||
5852 | ||||
5853 | RB (lang->has_type_conversion); | |||
5854 | RB (lang->has_copy_ctor); | |||
5855 | RB (lang->has_default_ctor); | |||
5856 | RB (lang->const_needs_init); | |||
5857 | RB (lang->ref_needs_init); | |||
5858 | RB (lang->has_const_copy_assign); | |||
5859 | unsigned v; | |||
5860 | v = b () << 0; | |||
5861 | v |= b () << 1; | |||
5862 | lang->use_template = v; | |||
5863 | ||||
5864 | RB (lang->has_mutable); | |||
5865 | RB (lang->com_interface); | |||
5866 | RB (lang->non_pod_class); | |||
5867 | RB (lang->nearly_empty_p); | |||
5868 | RB (lang->user_align); | |||
5869 | RB (lang->has_copy_assign); | |||
5870 | RB (lang->has_new); | |||
5871 | RB (lang->has_array_new); | |||
5872 | ||||
5873 | v = b () << 0; | |||
5874 | v |= b () << 1; | |||
5875 | lang->gets_delete = v; | |||
5876 | // lang->interface_only | |||
5877 | // lang->interface_unknown | |||
5878 | lang->interface_unknown = true; // Redetermine interface | |||
5879 | RB (lang->contains_empty_class_p); | |||
5880 | RB (lang->anon_aggr); | |||
5881 | RB (lang->non_zero_init); | |||
5882 | RB (lang->empty_p); | |||
5883 | ||||
5884 | RB (lang->vec_new_uses_cookie); | |||
5885 | RB (lang->declared_class); | |||
5886 | RB (lang->diamond_shaped); | |||
5887 | RB (lang->repeated_base); | |||
5888 | gcc_assert (!lang->being_defined)((void)(!(!lang->being_defined) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5888, __FUNCTION__), 0 : 0)); | |||
5889 | gcc_assert (!lang->debug_requested)((void)(!(!lang->debug_requested) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5889, __FUNCTION__), 0 : 0)); | |||
5890 | RB (lang->fields_readonly); | |||
5891 | RB (lang->ptrmemfunc_flag); | |||
5892 | ||||
5893 | RB (lang->lazy_default_ctor); | |||
5894 | RB (lang->lazy_copy_ctor); | |||
5895 | RB (lang->lazy_copy_assign); | |||
5896 | RB (lang->lazy_destructor); | |||
5897 | RB (lang->has_const_copy_ctor); | |||
5898 | RB (lang->has_complex_copy_ctor); | |||
5899 | RB (lang->has_complex_copy_assign); | |||
5900 | RB (lang->non_aggregate); | |||
5901 | ||||
5902 | RB (lang->has_complex_dflt); | |||
5903 | RB (lang->has_list_ctor); | |||
5904 | RB (lang->non_std_layout); | |||
5905 | RB (lang->is_literal); | |||
5906 | RB (lang->lazy_move_ctor); | |||
5907 | RB (lang->lazy_move_assign); | |||
5908 | RB (lang->has_complex_move_ctor); | |||
5909 | RB (lang->has_complex_move_assign); | |||
5910 | ||||
5911 | RB (lang->has_constexpr_ctor); | |||
5912 | RB (lang->unique_obj_representations); | |||
5913 | RB (lang->unique_obj_representations_set); | |||
5914 | #undef RB | |||
5915 | return !get_overrun (); | |||
5916 | } | |||
5917 | ||||
5918 | /* Read & write the core values and pointers. */ | |||
5919 | ||||
5920 | void | |||
5921 | trees_out::core_vals (tree t) | |||
5922 | { | |||
5923 | #define WU(X) (u (X)) | |||
5924 | #define WT(X) (tree_node (X)) | |||
5925 | tree_code code = TREE_CODE (t)((enum tree_code) (t)->base.code); | |||
5926 | ||||
5927 | /* First by shape of the tree. */ | |||
5928 | ||||
5929 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL)(tree_contains_struct[(code)][(TS_DECL_MINIMAL)])) | |||
5930 | { | |||
5931 | /* Write this early, for better log information. */ | |||
5932 | WT (t->decl_minimal.name); | |||
5933 | if (!DECL_TEMPLATE_PARM_P (t)(((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5933, __FUNCTION__))->decl_common.lang_flag_0) && (((enum tree_code) (t)->base.code) == CONST_DECL || ((enum tree_code) (t)->base.code) == PARM_DECL || ((enum tree_code ) (t)->base.code) == TYPE_DECL || ((enum tree_code) (t)-> base.code) == TEMPLATE_DECL))) | |||
5934 | WT (t->decl_minimal.context); | |||
5935 | ||||
5936 | if (state) | |||
5937 | state->write_location (*this, t->decl_minimal.locus); | |||
5938 | } | |||
5939 | ||||
5940 | if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)(tree_contains_struct[(code)][(TS_TYPE_COMMON)])) | |||
5941 | { | |||
5942 | /* The only types we write also have TYPE_NON_COMMON. */ | |||
5943 | gcc_checking_assert (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))((void)(!((tree_contains_struct[(code)][(TS_TYPE_NON_COMMON)] )) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5943, __FUNCTION__), 0 : 0)); | |||
5944 | ||||
5945 | /* We only stream the main variant. */ | |||
5946 | gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t)((void)(!(((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5946, __FUNCTION__))->type_common.main_variant) == t) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5946, __FUNCTION__), 0 : 0)); | |||
5947 | ||||
5948 | /* Stream the name & context first, for better log information */ | |||
5949 | WT (t->type_common.name); | |||
5950 | WT (t->type_common.context); | |||
5951 | ||||
5952 | /* By construction we want to make sure we have the canonical | |||
5953 | and main variants already in the type table, so emit them | |||
5954 | now. */ | |||
5955 | WT (t->type_common.main_variant); | |||
5956 | ||||
5957 | tree canonical = t->type_common.canonical; | |||
5958 | if (canonical && DECL_TEMPLATE_PARM_P (TYPE_NAME (t))(((contains_struct_check ((((tree_class_check ((t), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->type_common.name)), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->decl_common.lang_flag_0) && (((enum tree_code) (((tree_class_check ((t), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->type_common.name))->base.code) == CONST_DECL || ((enum tree_code) (((tree_class_check ((t), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->type_common.name))->base.code) == PARM_DECL || ((enum tree_code) (((tree_class_check ((t), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->type_common.name))->base.code) == TYPE_DECL || ((enum tree_code) (((tree_class_check ((t), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/cp/module.cc" , 5958, __FUNCTION__))->type_common.name))->base.code) == TEMPLATE_DECL))) | |||
5959 | /* We do not want to wander into different templates. | |||
5960 | Reconstructed on stream in. */ | |||
5961 | canonical = t; | |||
5962 | WT (canonical); | |||
5963 | ||||
5964 | /* type_common.next_variant is internally manipulated. */ | |||
5965 | /* type_common.pointer_to, type_common.reference_to. */ | |||
5966 | ||||
5967 | if (streaming_p ()) | |||
5968 | { | |||
5969 | WU (t->type_common.precision); | |||
5970 | WU (t->type_common.contains_placeholder_bits); | |||
5971 | WU (t->type_common.mode); | |||
5972 | WU (t->type_common.align); | |||
5973 | } | |||
5974 | ||||
5975 | if (!RECORD_OR_UNION_CODE_P (code)((code) == RECORD_TYPE || (code) == UNION_TYPE)) | |||
5976 | { | |||
5977 | WT (t->type_common.size); | |||
5978 | WT (t->type_common.size_unit); | |||
5979 | } | |||
5980 | WT (t->type_common.attributes); | |||
5981 | ||||
5982 | WT (t->type_common.common.chain); /* TYPE_STUB_DECL. */ | |||
5983 | } | |||
5984 | ||||
5985 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)(tree_contains_struct[(code)][(TS_DECL_COMMON)])) | |||
5986 | { | |||
5987 | if (streaming_p ()) | |||
5988 | { | |||
5989 | WU (t->decl_common.mode); | |||
5990 | WU (t->decl_common.off_align); | |||
5991 | WU (t->decl_common.align); | |||
5992 | } | |||
5993 | ||||
5994 | /* For templates these hold instantiation (partial and/or | |||
5995 | specialization) information. */ | |||
5996 | if (code != TEMPLATE_DECL) | |||
5997 | { | |||
5998 | WT (t->decl_common.size); | |||
5999 | WT (t->decl_common.size_unit); | |||
6000 | } | |||
6001 | ||||
6002 | WT (t->decl_common.attributes); | |||
6003 | // FIXME: Does this introduce cross-decl links? For instance | |||
6004 | // from instantiation to the template. If so, we'll need more | |||
6005 | // deduplication logic. I think we'll need to walk the blocks | |||
6006 | // of the owning function_decl's abstract origin in tandem, to | |||
6007 | // generate the locating data needed? | |||
6008 | WT (t->decl_common.abstract_origin); | |||
6009 | } | |||
6010 | ||||
6011 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)(tree_contains_struct[(code)][(TS_DECL_WITH_VIS)])) | |||
6012 | { | |||
6013 | WT (t->decl_with_vis.assembler_name); | |||
6014 | if (streaming_p ()) | |||
6015 | WU (t->decl_with_vis.visibility); | |||
6016 | } | |||
6017 | ||||
6018 | if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON)(tree_contains_struct[(code)][(TS_TYPE_NON_COMMON)])) | |||
6019 | { | |||
6020 | if (code == ENUMERAL_TYPE) | |||
6021 | { | |||
6022 | /* These fields get set even for opaque enums that lack a | |||
6023 | definition, so we stream them directly for each ENUMERAL_TYPE. | |||
6024 | We stream TYPE_VALUES as part of the definition. */ | |||
6025 | WT (t->type_non_common.maxval); | |||
6026 | WT (t->type_non_common.minval); | |||
6027 | } | |||
6028 | /* Records and unions hold FIELDS, VFIELD & BINFO on these | |||
6029 | things. */ | |||
6030 | else if (!RECORD_OR_UNION_CODE_P (code)((code) == RECORD_TYPE || (code) == UNION_TYPE)) | |||
6031 | { | |||
6032 | // FIXME: These are from tpl_parm_value's 'type' writing. | |||
6033 | // Perhaps it should just be doing them directly? | |||