File: | build/gcc/cp/module.cc |
Warning: | line 16463, column 4 Forming reference to null pointer |
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); |