]>
Commit | Line | Data |
---|---|---|
8d08fdba MS |
1 | /* Handle the hair of processing (but not expanding) inline functions. |
2 | Also manage function and variable name overloading. | |
31bebb60 | 3 | Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc. |
8d08fdba MS |
4 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
5 | ||
e5e809f4 | 6 | This file is part of GNU CC. |
8d08fdba MS |
7 | |
8 | GNU CC is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU CC is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU CC; see the file COPYING. If not, write to | |
e9fa0c7c RK |
20 | the Free Software Foundation, 59 Temple Place - Suite 330, |
21 | Boston, MA 02111-1307, USA. */ | |
8d08fdba MS |
22 | |
23 | ||
ed22c95e AM |
24 | #ifndef __GNUC__ |
25 | #define __inline | |
26 | #endif | |
27 | ||
8d08fdba MS |
28 | #ifndef PARM_CAN_BE_ARRAY_TYPE |
29 | #define PARM_CAN_BE_ARRAY_TYPE 1 | |
30 | #endif | |
31 | ||
32 | /* Handle method declarations. */ | |
8d08fdba | 33 | #include "config.h" |
e817b5e3 | 34 | #include "system.h" |
8d08fdba MS |
35 | #include "tree.h" |
36 | #include "cp-tree.h" | |
8d08fdba | 37 | #include "obstack.h" |
8926095f MS |
38 | #include "rtl.h" |
39 | #include "expr.h" | |
40 | #include "output.h" | |
41 | #include "hard-reg-set.h" | |
42 | #include "flags.h" | |
54f92bfb | 43 | #include "toplev.h" |
8d08fdba MS |
44 | |
45 | /* TREE_LIST of the current inline functions that need to be | |
46 | processed. */ | |
47 | struct pending_inline *pending_inlines; | |
48 | ||
42976354 BK |
49 | int static_labelno; |
50 | ||
8d08fdba MS |
51 | #define obstack_chunk_alloc xmalloc |
52 | #define obstack_chunk_free free | |
53 | ||
54 | /* Obstack where we build text strings for overloading, etc. */ | |
55 | static struct obstack scratch_obstack; | |
56 | static char *scratch_firstobj; | |
57 | ||
49c249e1 JM |
58 | static void icat PROTO((HOST_WIDE_INT)); |
59 | static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT)); | |
59e621fc | 60 | static void flush_repeats PROTO((int, tree)); |
49c249e1 JM |
61 | static void build_overload_identifier PROTO((tree)); |
62 | static void build_overload_nested_name PROTO((tree)); | |
37dac039 | 63 | static void build_overload_int PROTO((tree, int)); |
49c249e1 JM |
64 | static void build_overload_identifier PROTO((tree)); |
65 | static void build_qualified_name PROTO((tree)); | |
37dac039 | 66 | static void build_overload_value PROTO((tree, tree, int)); |
59e621fc | 67 | static void issue_nrepeats PROTO((int, tree)); |
ed22c95e AM |
68 | static char *build_mangled_name PROTO((tree,int,int)); |
69 | static void process_modifiers PROTO((tree)); | |
70 | static void process_overload_item PROTO((tree,int)); | |
49c249e1 JM |
71 | static void do_build_assign_ref PROTO((tree)); |
72 | static void do_build_copy_constructor PROTO((tree)); | |
73 | static tree largest_union_member PROTO((tree)); | |
73b0fce8 | 74 | static void build_template_template_parm_names PROTO((tree)); |
386b8a85 JM |
75 | static void build_template_parm_names PROTO((tree, tree)); |
76 | static void build_underscore_int PROTO((int)); | |
47c78a3f JL |
77 | static void start_squangling PROTO((void)); |
78 | static void end_squangling PROTO((void)); | |
69ac77ce JL |
79 | static int check_ktype PROTO((tree, int)); |
80 | static int issue_ktype PROTO((tree)); | |
47c78a3f | 81 | static void build_overload_scope_ref PROTO((tree)); |
69ac77ce | 82 | static void build_mangled_template_parm_index PROTO((char *, tree)); |
59e621fc | 83 | static int is_back_referenceable_type PROTO((tree)); |
69ac77ce | 84 | static int check_btype PROTO((tree)); |
59e621fc MM |
85 | static void build_mangled_name_for_type PROTO((tree)); |
86 | static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); | |
49c249e1 | 87 | |
8d08fdba MS |
88 | # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) |
89 | # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) | |
90 | # define OB_PUTC2(C1,C2) \ | |
91 | (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2))) | |
92 | # define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1)) | |
93 | # define OB_PUTID(ID) \ | |
94 | (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \ | |
95 | IDENTIFIER_LENGTH (ID))) | |
96 | # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S))) | |
97 | # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0')) | |
db5ae43f | 98 | # define OB_LAST() (obstack_next_free (&scratch_obstack)[-1]) |
8d08fdba | 99 | |
8d08fdba MS |
100 | void |
101 | init_method () | |
102 | { | |
103 | gcc_obstack_init (&scratch_obstack); | |
104 | scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0); | |
105 | } | |
106 | ||
107 | /* This must be large enough to hold any printed integer or floating-point | |
108 | value. */ | |
109 | static char digit_buffer[128]; | |
110 | ||
111 | /* Move inline function definitions out of structure so that they | |
112 | can be processed normally. CNAME is the name of the class | |
113 | we are working from, METHOD_LIST is the list of method lists | |
114 | of the structure. We delete friend methods here, after | |
115 | saving away their inline function definitions (if any). */ | |
116 | ||
117 | void | |
118 | do_inline_function_hair (type, friend_list) | |
119 | tree type, friend_list; | |
120 | { | |
121 | tree method = TYPE_METHODS (type); | |
122 | ||
123 | if (method && TREE_CODE (method) == TREE_VEC) | |
124 | { | |
fc378698 MS |
125 | if (TREE_VEC_ELT (method, 1)) |
126 | method = TREE_VEC_ELT (method, 1); | |
127 | else if (TREE_VEC_ELT (method, 0)) | |
8d08fdba MS |
128 | method = TREE_VEC_ELT (method, 0); |
129 | else | |
fc378698 | 130 | method = TREE_VEC_ELT (method, 2); |
8d08fdba MS |
131 | } |
132 | ||
133 | while (method) | |
134 | { | |
135 | /* Do inline member functions. */ | |
136 | struct pending_inline *info = DECL_PENDING_INLINE_INFO (method); | |
137 | if (info) | |
138 | { | |
139 | tree args; | |
140 | ||
141 | my_friendly_assert (info->fndecl == method, 238); | |
142 | args = DECL_ARGUMENTS (method); | |
143 | while (args) | |
144 | { | |
145 | DECL_CONTEXT (args) = method; | |
146 | args = TREE_CHAIN (args); | |
147 | } | |
8d08fdba MS |
148 | } |
149 | method = TREE_CHAIN (method); | |
150 | } | |
151 | while (friend_list) | |
152 | { | |
153 | tree fndecl = TREE_VALUE (friend_list); | |
154 | struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl); | |
155 | if (info) | |
156 | { | |
157 | tree args; | |
158 | ||
159 | my_friendly_assert (info->fndecl == fndecl, 239); | |
160 | args = DECL_ARGUMENTS (fndecl); | |
161 | while (args) | |
162 | { | |
163 | DECL_CONTEXT (args) = fndecl; | |
164 | args = TREE_CHAIN (args); | |
165 | } | |
8d08fdba MS |
166 | } |
167 | ||
168 | friend_list = TREE_CHAIN (friend_list); | |
169 | } | |
170 | } | |
171 | \f | |
8d08fdba MS |
172 | /* Here is where overload code starts. */ |
173 | ||
ed22c95e AM |
174 | /* type tables for K and B type compression */ |
175 | static tree *btypelist = NULL; | |
176 | static tree *ktypelist = NULL; | |
ed22c95e AM |
177 | static int maxbsize = 0; |
178 | static int maxksize = 0; | |
179 | ||
180 | /* number of each type seen */ | |
181 | static int maxbtype = 0; | |
182 | static int maxktype = 0; | |
183 | ||
ed22c95e | 184 | /* Array of types seen so far in top-level call to `build_mangled_name'. |
8d08fdba | 185 | Allocated and deallocated by caller. */ |
ed22c95e | 186 | static tree *typevec = NULL; |
2c73f9f5 | 187 | static int typevec_size; |
8d08fdba | 188 | |
ed22c95e AM |
189 | /* Number of types interned by `build_mangled_name' so far. */ |
190 | static int maxtype = 0; | |
8d08fdba | 191 | |
8d08fdba MS |
192 | /* Nonzero if we should not try folding parameter types. */ |
193 | static int nofold; | |
194 | ||
ed22c95e AM |
195 | /* This appears to be set to true if an underscore is required to be |
196 | comcatenated before another number can be outputed. */ | |
197 | static int numeric_output_need_bar; | |
8d08fdba | 198 | |
ed22c95e AM |
199 | static __inline void |
200 | start_squangling () | |
201 | { | |
202 | if (flag_do_squangling) | |
203 | { | |
ed22c95e | 204 | nofold = 0; |
ed22c95e AM |
205 | maxbtype = 0; |
206 | maxktype = 0; | |
207 | maxbsize = 50; | |
208 | maxksize = 50; | |
209 | btypelist = (tree *)xmalloc (sizeof (tree) * maxbsize); | |
210 | ktypelist = (tree *)xmalloc (sizeof (tree) * maxksize); | |
211 | } | |
212 | } | |
213 | ||
214 | static __inline void | |
215 | end_squangling () | |
216 | { | |
217 | if (flag_do_squangling) | |
218 | { | |
ed22c95e AM |
219 | if (ktypelist) |
220 | free (ktypelist); | |
221 | if (btypelist) | |
222 | free (btypelist); | |
223 | maxbsize = 0; | |
224 | maxksize = 0; | |
225 | maxbtype = 0; | |
226 | maxktype = 0; | |
227 | ktypelist = NULL; | |
228 | btypelist = NULL; | |
229 | } | |
230 | } | |
8d08fdba MS |
231 | |
232 | /* Code to concatenate an asciified integer to a string. */ | |
e92cc029 | 233 | |
ed22c95e | 234 | static __inline void |
8d08fdba | 235 | icat (i) |
bd6dd845 | 236 | HOST_WIDE_INT i; |
8d08fdba | 237 | { |
bd6dd845 MS |
238 | unsigned HOST_WIDE_INT ui; |
239 | ||
8d08fdba | 240 | /* Handle this case first, to go really quickly. For many common values, |
bd6dd845 | 241 | the result of ui/10 below is 1. */ |
8d08fdba MS |
242 | if (i == 1) |
243 | { | |
244 | OB_PUTC ('1'); | |
245 | return; | |
246 | } | |
247 | ||
bd6dd845 MS |
248 | if (i >= 0) |
249 | ui = i; | |
250 | else | |
8d08fdba MS |
251 | { |
252 | OB_PUTC ('m'); | |
bd6dd845 MS |
253 | ui = -i; |
254 | } | |
255 | ||
256 | if (ui >= 10) | |
257 | icat (ui / 10); | |
258 | ||
259 | OB_PUTC ('0' + (ui % 10)); | |
260 | } | |
261 | ||
262 | static void | |
263 | dicat (lo, hi) | |
264 | HOST_WIDE_INT lo, hi; | |
265 | { | |
266 | unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi; | |
267 | ||
268 | if (hi >= 0) | |
269 | { | |
270 | uhi = hi; | |
271 | ulo = lo; | |
8d08fdba | 272 | } |
8d08fdba MS |
273 | else |
274 | { | |
bd6dd845 MS |
275 | uhi = (lo == 0 ? -hi : -hi-1); |
276 | ulo = -lo; | |
277 | } | |
278 | if (uhi == 0 | |
279 | && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1))) | |
280 | { | |
281 | icat (ulo); | |
282 | return; | |
8d08fdba | 283 | } |
bd6dd845 MS |
284 | /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */ |
285 | qhi = uhi / 10; | |
286 | uhi = uhi % 10; | |
287 | qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5); | |
288 | qlo += ulo / 10; | |
289 | ulo = ulo % 10; | |
290 | ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5) | |
291 | * 2; | |
292 | qlo += ulo / 10; | |
293 | ulo = ulo % 10; | |
294 | /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */ | |
295 | dicat (qlo, qhi); | |
296 | OB_PUTC ('0' + ulo); | |
8d08fdba MS |
297 | } |
298 | ||
744fac59 | 299 | static __inline void |
59e621fc MM |
300 | flush_repeats (nrepeats, type) |
301 | int nrepeats; | |
8d08fdba MS |
302 | tree type; |
303 | { | |
304 | int tindex = 0; | |
305 | ||
306 | while (typevec[tindex] != type) | |
307 | tindex++; | |
308 | ||
59e621fc | 309 | if (nrepeats > 1) |
8d08fdba MS |
310 | { |
311 | OB_PUTC ('N'); | |
59e621fc MM |
312 | icat (nrepeats); |
313 | if (nrepeats > 9) | |
8d08fdba MS |
314 | OB_PUTC ('_'); |
315 | } | |
316 | else | |
317 | OB_PUTC ('T'); | |
8d08fdba MS |
318 | icat (tindex); |
319 | if (tindex > 9) | |
320 | OB_PUTC ('_'); | |
321 | } | |
322 | ||
59e621fc MM |
323 | /* Returns nonzero iff this is a type to which we will want to make |
324 | back-references (using the `B' code). */ | |
ed22c95e | 325 | |
59e621fc MM |
326 | int |
327 | is_back_referenceable_type (type) | |
328 | tree type; | |
ed22c95e | 329 | { |
59e621fc MM |
330 | if (btypelist == NULL) |
331 | /* We're not generating any back-references. */ | |
332 | return 0; | |
333 | ||
334 | switch (TREE_CODE (type)) | |
ed22c95e | 335 | { |
59e621fc MM |
336 | case INTEGER_TYPE: |
337 | case REAL_TYPE: | |
338 | case VOID_TYPE: | |
339 | case BOOLEAN_TYPE: | |
340 | /* These types have single-character manglings, so there's no | |
341 | point in generating back-references. */ | |
342 | return 0; | |
343 | ||
344 | case TEMPLATE_TYPE_PARM: | |
345 | /* It would be a bit complex to demangle signatures correctly if | |
346 | we generated back-references to these, and the manglings of | |
347 | type parameters are short. */ | |
348 | return 0; | |
349 | ||
350 | default: | |
351 | return 1; | |
ed22c95e | 352 | } |
ed22c95e AM |
353 | } |
354 | ||
59e621fc MM |
355 | /* Issue the squangling code indicating NREPEATS repetitions of TYPE, |
356 | which was the last parameter type output. */ | |
357 | ||
358 | static void | |
359 | issue_nrepeats (nrepeats, type) | |
360 | int nrepeats; | |
361 | tree type; | |
362 | { | |
363 | if (nrepeats == 1 && !is_back_referenceable_type (type)) | |
364 | /* For types whose manglings are short, don't bother using the | |
365 | repetition code if there's only one repetition, since the | |
366 | repetition code will be about as long as the ordinary mangling. */ | |
367 | build_mangled_name_for_type (type); | |
368 | else | |
369 | { | |
370 | OB_PUTC ('n'); | |
371 | icat (nrepeats); | |
372 | if (nrepeats > 9) | |
373 | OB_PUTC ('_'); | |
374 | } | |
375 | } | |
ed22c95e AM |
376 | |
377 | /* Check to see if a tree node has been entered into the Kcode typelist */ | |
378 | /* if not, add it. Return -1 if it isn't found, otherwise return the index */ | |
379 | static int | |
380 | check_ktype (node, add) | |
381 | tree node; | |
382 | int add; | |
383 | { | |
384 | int x; | |
385 | tree localnode = node; | |
386 | ||
387 | if (ktypelist == NULL) | |
388 | return -1; | |
389 | ||
390 | if (TREE_CODE (node) == TYPE_DECL) | |
391 | localnode = TREE_TYPE (node); | |
392 | ||
393 | for (x=0; x < maxktype; x++) | |
394 | { | |
395 | if (localnode == ktypelist[x]) | |
396 | return x ; | |
397 | } | |
398 | /* Didn't find it, so add it here */ | |
399 | if (add) | |
400 | { | |
401 | if (maxksize <= maxktype) | |
402 | { | |
403 | maxksize = maxksize* 3 / 2; | |
e06e4d45 | 404 | ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize); |
ed22c95e AM |
405 | } |
406 | ktypelist[maxktype++] = localnode; | |
407 | } | |
408 | return -1; | |
409 | } | |
410 | ||
411 | ||
412 | static __inline int | |
413 | issue_ktype (decl) | |
414 | tree decl; | |
415 | { | |
416 | int kindex; | |
417 | kindex = check_ktype (decl, FALSE); | |
418 | if (kindex != -1) | |
419 | { | |
420 | OB_PUTC ('K'); | |
421 | icat (kindex); | |
422 | if (kindex > 9) | |
423 | OB_PUTC ('_'); | |
424 | return TRUE; | |
425 | } | |
426 | return FALSE; | |
427 | } | |
59e621fc MM |
428 | |
429 | /* Build a representation for DECL, which may be an entity not at | |
430 | global scope. If so, a marker indicating that the name is | |
431 | qualified has already been output, but the qualifying context has | |
432 | not. */ | |
8d08fdba MS |
433 | |
434 | static void | |
db5ae43f MS |
435 | build_overload_nested_name (decl) |
436 | tree decl; | |
8d08fdba | 437 | { |
cb0dbb9a JM |
438 | tree context; |
439 | ||
ed22c95e AM |
440 | if (ktypelist && issue_ktype (decl)) |
441 | return; | |
442 | ||
2c73f9f5 ML |
443 | if (decl == global_namespace) |
444 | return; | |
445 | ||
cb0dbb9a JM |
446 | context = CP_DECL_CONTEXT (decl); |
447 | ||
448 | /* try to issue a K type, and if we can't continue the normal path */ | |
449 | if (!(ktypelist && issue_ktype (context))) | |
450 | { | |
451 | /* For a template type parameter, we want to output an 'Xn' | |
452 | rather than 'T' or some such. */ | |
453 | if (TREE_CODE (context) == TEMPLATE_TYPE_PARM | |
454 | || TREE_CODE (context) == TEMPLATE_TEMPLATE_PARM) | |
59e621fc | 455 | build_mangled_name_for_type (context); |
cb0dbb9a | 456 | else |
8d08fdba | 457 | { |
cb0dbb9a JM |
458 | if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') |
459 | context = TYPE_NAME (context); | |
460 | build_overload_nested_name (context); | |
8d08fdba | 461 | } |
cb0dbb9a | 462 | } |
ed22c95e | 463 | |
db5ae43f MS |
464 | if (TREE_CODE (decl) == FUNCTION_DECL) |
465 | { | |
466 | tree name = DECL_ASSEMBLER_NAME (decl); | |
467 | char *label; | |
db5ae43f | 468 | |
42976354 BK |
469 | ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno); |
470 | static_labelno++; | |
db5ae43f | 471 | |
8cb9cd5d | 472 | if (numeric_output_need_bar) |
42976354 | 473 | OB_PUTC ('_'); |
db5ae43f MS |
474 | icat (strlen (label)); |
475 | OB_PUTCP (label); | |
42976354 | 476 | numeric_output_need_bar = 1; |
db5ae43f | 477 | } |
30394414 JM |
478 | else if (TREE_CODE (decl) == NAMESPACE_DECL) |
479 | build_overload_identifier (DECL_NAME (decl)); | |
db5ae43f | 480 | else /* TYPE_DECL */ |
5566b478 | 481 | build_overload_identifier (decl); |
8d08fdba MS |
482 | } |
483 | ||
59e621fc MM |
484 | /* Output the decimal representation of I. If I > 9, the decimal |
485 | representation is preceeded and followed by an underscore. */ | |
486 | ||
386b8a85 | 487 | static void |
c8907853 JL |
488 | build_underscore_int (i) |
489 | int i; | |
386b8a85 JM |
490 | { |
491 | if (i > 9) | |
492 | OB_PUTC ('_'); | |
493 | icat (i); | |
494 | if (i > 9) | |
c32381b1 | 495 | OB_PUTC ('_'); |
386b8a85 JM |
496 | } |
497 | ||
050367a3 MM |
498 | static void |
499 | build_overload_scope_ref (value) | |
500 | tree value; | |
501 | { | |
502 | OB_PUTC2 ('Q', '2'); | |
503 | numeric_output_need_bar = 0; | |
59e621fc | 504 | build_mangled_name_for_type (TREE_OPERAND (value, 0)); |
050367a3 MM |
505 | build_overload_identifier (TREE_OPERAND (value, 1)); |
506 | } | |
507 | ||
e92cc029 MS |
508 | /* Encoding for an INTEGER_CST value. */ |
509 | ||
e1b7b0cb | 510 | static void |
37dac039 | 511 | build_overload_int (value, in_template) |
e1b7b0cb | 512 | tree value; |
37dac039 | 513 | int in_template; |
e1b7b0cb | 514 | { |
2636fde4 | 515 | if (in_template && TREE_CODE (value) != INTEGER_CST) |
5566b478 | 516 | { |
050367a3 MM |
517 | if (TREE_CODE (value) == SCOPE_REF) |
518 | { | |
519 | build_overload_scope_ref (value); | |
520 | return; | |
521 | } | |
522 | ||
523 | OB_PUTC ('E'); | |
524 | numeric_output_need_bar = 0; | |
525 | ||
526 | if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (value)))) | |
527 | { | |
528 | int i; | |
529 | int operands = tree_code_length[(int) TREE_CODE (value)]; | |
530 | tree id; | |
531 | char* name; | |
532 | ||
533 | id = ansi_opname [(int) TREE_CODE (value)]; | |
534 | my_friendly_assert (id != NULL_TREE, 0); | |
535 | name = IDENTIFIER_POINTER (id); | |
67ffc812 MM |
536 | if (name[0] != '_' || name[1] != '_') |
537 | /* On some erroneous inputs, we can get here with VALUE a | |
538 | LOOKUP_EXPR. In that case, the NAME will be the | |
539 | identifier for "<invalid operator>". We must survive | |
540 | this routine in order to issue a sensible error | |
541 | message, so we fall through to the case below. */ | |
542 | goto bad_value; | |
050367a3 MM |
543 | |
544 | for (i = 0; i < operands; ++i) | |
545 | { | |
546 | tree operand; | |
547 | enum tree_code tc; | |
548 | ||
549 | /* We just outputted either the `E' or the name of the | |
550 | operator. */ | |
551 | numeric_output_need_bar = 0; | |
552 | ||
553 | if (i != 0) | |
554 | /* Skip the leading underscores. */ | |
555 | OB_PUTCP (name + 2); | |
556 | ||
557 | operand = TREE_OPERAND (value, i); | |
558 | tc = TREE_CODE (operand); | |
559 | ||
560 | if (TREE_CODE_CLASS (tc) == 't') | |
561 | /* We can get here with sizeof, e.g.: | |
562 | ||
563 | template <class T> void f(A<sizeof(T)>); */ | |
59e621fc | 564 | build_mangled_name_for_type (operand); |
050367a3 MM |
565 | else if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (tc))) |
566 | build_overload_int (operand, in_template); | |
567 | else | |
568 | build_overload_value (TREE_TYPE (operand), | |
569 | operand, | |
570 | in_template); | |
571 | } | |
572 | } | |
573 | else | |
574 | { | |
575 | /* We don't ever want this output, but it's | |
576 | inconvenient not to be able to build the string. | |
577 | This should cause assembler errors we'll notice. */ | |
578 | ||
579 | static int n; | |
67ffc812 | 580 | bad_value: |
050367a3 MM |
581 | sprintf (digit_buffer, " *%d", n++); |
582 | OB_PUTCP (digit_buffer); | |
583 | } | |
584 | ||
585 | OB_PUTC ('W'); | |
586 | numeric_output_need_bar = 0; | |
5566b478 MS |
587 | return; |
588 | } | |
589 | ||
e1b7b0cb | 590 | my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); |
5156628f | 591 | if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) |
e1b7b0cb | 592 | { |
e1b7b0cb RK |
593 | if (TREE_INT_CST_HIGH (value) |
594 | != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) | |
595 | { | |
596 | /* need to print a DImode value in decimal */ | |
bd6dd845 | 597 | dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); |
050367a3 | 598 | numeric_output_need_bar = 1; |
bd6dd845 | 599 | return; |
e1b7b0cb RK |
600 | } |
601 | /* else fall through to print in smaller mode */ | |
602 | } | |
603 | /* Wordsize or smaller */ | |
604 | icat (TREE_INT_CST_LOW (value)); | |
050367a3 | 605 | numeric_output_need_bar = 1; |
e1b7b0cb RK |
606 | } |
607 | ||
f84b4be9 JM |
608 | |
609 | /* Output S followed by a representation of the TEMPLATE_PARM_INDEX | |
610 | supplied in INDEX. */ | |
611 | ||
612 | static void | |
613 | build_mangled_template_parm_index (s, index) | |
614 | char* s; | |
615 | tree index; | |
616 | { | |
617 | OB_PUTCP (s); | |
618 | build_underscore_int (TEMPLATE_PARM_IDX (index)); | |
619 | /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a | |
620 | representation of the function from the point of view of its | |
621 | type. */ | |
622 | build_underscore_int (TEMPLATE_PARM_LEVEL (index)); | |
623 | } | |
624 | ||
625 | ||
8d08fdba | 626 | static void |
37dac039 | 627 | build_overload_value (type, value, in_template) |
8d08fdba | 628 | tree type, value; |
37dac039 | 629 | int in_template; |
8d08fdba MS |
630 | { |
631 | while (TREE_CODE (value) == NON_LVALUE_EXPR | |
632 | || TREE_CODE (value) == NOP_EXPR) | |
633 | value = TREE_OPERAND (value, 0); | |
050367a3 MM |
634 | |
635 | if (TREE_CODE (type) == PARM_DECL) | |
636 | type = TREE_TYPE (type); | |
637 | ||
638 | my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (type)) == 't', 0); | |
e1b7b0cb RK |
639 | |
640 | if (numeric_output_need_bar) | |
641 | { | |
642 | OB_PUTC ('_'); | |
643 | numeric_output_need_bar = 0; | |
644 | } | |
645 | ||
f84b4be9 | 646 | if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) |
2636fde4 | 647 | { |
f84b4be9 | 648 | build_mangled_template_parm_index ("Y", value); |
2636fde4 JM |
649 | return; |
650 | } | |
651 | ||
8145f082 MS |
652 | if (TREE_CODE (type) == POINTER_TYPE |
653 | && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) | |
654 | { | |
e1b7b0cb | 655 | /* Handle a pointer to data member as a template instantiation |
8145f082 MS |
656 | parameter, boy, what fun! */ |
657 | type = integer_type_node; | |
658 | if (TREE_CODE (value) != INTEGER_CST) | |
659 | { | |
660 | sorry ("unknown pointer to member constant"); | |
661 | return; | |
662 | } | |
663 | } | |
664 | ||
e1b7b0cb RK |
665 | if (TYPE_PTRMEMFUNC_P (type)) |
666 | type = TYPE_PTRMEMFUNC_FN_TYPE (type); | |
667 | ||
8d08fdba MS |
668 | switch (TREE_CODE (type)) |
669 | { | |
670 | case INTEGER_TYPE: | |
671 | case ENUMERAL_TYPE: | |
2986ae00 MS |
672 | case BOOLEAN_TYPE: |
673 | { | |
37dac039 | 674 | build_overload_int (value, in_template); |
2986ae00 MS |
675 | return; |
676 | } | |
8d08fdba MS |
677 | case REAL_TYPE: |
678 | { | |
679 | REAL_VALUE_TYPE val; | |
680 | char *bufp = digit_buffer; | |
8d08fdba | 681 | |
bd6dd845 MS |
682 | pedwarn ("ANSI C++ forbids floating-point template arguments"); |
683 | ||
8d08fdba MS |
684 | my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); |
685 | val = TREE_REAL_CST (value); | |
bd6dd845 | 686 | if (REAL_VALUE_ISNAN (val)) |
8d08fdba | 687 | { |
bd6dd845 | 688 | sprintf (bufp, "NaN"); |
8d08fdba | 689 | } |
8d08fdba MS |
690 | else |
691 | { | |
bd6dd845 | 692 | if (REAL_VALUE_NEGATIVE (val)) |
8d08fdba | 693 | { |
bd6dd845 | 694 | val = REAL_VALUE_NEGATE (val); |
8d08fdba MS |
695 | *bufp++ = 'm'; |
696 | } | |
bd6dd845 | 697 | if (REAL_VALUE_ISINF (val)) |
8d08fdba | 698 | { |
bd6dd845 | 699 | sprintf (bufp, "Infinity"); |
8d08fdba | 700 | } |
bd6dd845 | 701 | else |
8d08fdba | 702 | { |
3d015f46 | 703 | REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp); |
bd6dd845 MS |
704 | bufp = (char *) index (bufp, 'e'); |
705 | if (!bufp) | |
706 | strcat (digit_buffer, "e0"); | |
707 | else | |
708 | { | |
709 | char *p; | |
710 | bufp++; | |
711 | if (*bufp == '-') | |
712 | { | |
713 | *bufp++ = 'm'; | |
714 | } | |
715 | p = bufp; | |
716 | if (*p == '+') | |
717 | p++; | |
718 | while (*p == '0') | |
719 | p++; | |
720 | if (*p == 0) | |
721 | { | |
722 | *bufp++ = '0'; | |
723 | *bufp = 0; | |
724 | } | |
725 | else if (p != bufp) | |
726 | { | |
727 | while (*p) | |
728 | *bufp++ = *p++; | |
729 | *bufp = 0; | |
730 | } | |
731 | } | |
732 | #ifdef NO_DOT_IN_LABEL | |
733 | bufp = (char *) index (bufp, '.'); | |
734 | if (bufp) | |
735 | *bufp = '_'; | |
736 | #endif | |
8d08fdba MS |
737 | } |
738 | } | |
739 | OB_PUTCP (digit_buffer); | |
e1b7b0cb | 740 | numeric_output_need_bar = 1; |
8d08fdba MS |
741 | return; |
742 | } | |
8d08fdba | 743 | case POINTER_TYPE: |
e1b7b0cb RK |
744 | if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE |
745 | && TREE_CODE (value) != ADDR_EXPR) | |
746 | { | |
747 | if (TREE_CODE (value) == CONSTRUCTOR) | |
748 | { | |
e92cc029 | 749 | /* This is dangerous code, crack built up pointer to members. */ |
e1b7b0cb RK |
750 | tree args = CONSTRUCTOR_ELTS (value); |
751 | tree a1 = TREE_VALUE (args); | |
752 | tree a2 = TREE_VALUE (TREE_CHAIN (args)); | |
753 | tree a3 = CONSTRUCTOR_ELTS (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)))); | |
754 | a3 = TREE_VALUE (a3); | |
755 | STRIP_NOPS (a3); | |
756 | if (TREE_CODE (a1) == INTEGER_CST | |
757 | && TREE_CODE (a2) == INTEGER_CST) | |
758 | { | |
37dac039 | 759 | build_overload_int (a1, in_template); |
e1b7b0cb | 760 | OB_PUTC ('_'); |
37dac039 | 761 | build_overload_int (a2, in_template); |
e1b7b0cb RK |
762 | OB_PUTC ('_'); |
763 | if (TREE_CODE (a3) == ADDR_EXPR) | |
764 | { | |
765 | a3 = TREE_OPERAND (a3, 0); | |
766 | if (TREE_CODE (a3) == FUNCTION_DECL) | |
767 | { | |
768 | numeric_output_need_bar = 0; | |
769 | build_overload_identifier (DECL_ASSEMBLER_NAME (a3)); | |
770 | return; | |
771 | } | |
772 | } | |
773 | else if (TREE_CODE (a3) == INTEGER_CST) | |
774 | { | |
775 | OB_PUTC ('i'); | |
37dac039 | 776 | build_overload_int (a3, in_template); |
e1b7b0cb RK |
777 | return; |
778 | } | |
779 | } | |
780 | } | |
781 | sorry ("template instantiation with pointer to method that is too complex"); | |
782 | return; | |
783 | } | |
f84b4be9 | 784 | if (TREE_CODE (value) == INTEGER_CST) |
f30432d7 | 785 | { |
37dac039 | 786 | build_overload_int (value, in_template); |
f30432d7 MS |
787 | return; |
788 | } | |
f84b4be9 JM |
789 | else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX) |
790 | { | |
791 | build_mangled_template_parm_index ("", value); | |
792 | numeric_output_need_bar = 1; | |
793 | return; | |
794 | } | |
795 | ||
8d08fdba MS |
796 | value = TREE_OPERAND (value, 0); |
797 | if (TREE_CODE (value) == VAR_DECL) | |
798 | { | |
799 | my_friendly_assert (DECL_NAME (value) != 0, 245); | |
e76a2646 | 800 | build_overload_identifier (DECL_ASSEMBLER_NAME (value)); |
8d08fdba MS |
801 | return; |
802 | } | |
803 | else if (TREE_CODE (value) == FUNCTION_DECL) | |
804 | { | |
805 | my_friendly_assert (DECL_NAME (value) != 0, 246); | |
e76a2646 | 806 | build_overload_identifier (DECL_ASSEMBLER_NAME (value)); |
8d08fdba MS |
807 | return; |
808 | } | |
aa36c081 | 809 | else if (TREE_CODE (value) == SCOPE_REF) |
050367a3 | 810 | build_overload_scope_ref (value); |
8d08fdba MS |
811 | else |
812 | my_friendly_abort (71); | |
813 | break; /* not really needed */ | |
814 | ||
815 | default: | |
816 | sorry ("conversion of %s as template parameter", | |
817 | tree_code_name [(int) TREE_CODE (type)]); | |
818 | my_friendly_abort (72); | |
819 | } | |
820 | } | |
821 | ||
386b8a85 | 822 | |
73b0fce8 KL |
823 | /* Add encodings for the declaration of template template parameters. |
824 | PARMLIST must be a TREE_VEC */ | |
825 | ||
826 | static void | |
827 | build_template_template_parm_names (parmlist) | |
828 | tree parmlist; | |
829 | { | |
830 | int i, nparms; | |
831 | ||
832 | my_friendly_assert (TREE_CODE (parmlist) == TREE_VEC, 246.5); | |
833 | nparms = TREE_VEC_LENGTH (parmlist); | |
834 | icat (nparms); | |
835 | for (i = 0; i < nparms; i++) | |
836 | { | |
837 | tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); | |
838 | if (TREE_CODE (parm) == TYPE_DECL) | |
839 | { | |
840 | /* This parameter is a type. */ | |
841 | OB_PUTC ('Z'); | |
842 | } | |
843 | else if (TREE_CODE (parm) == TEMPLATE_DECL) | |
844 | { | |
845 | /* This parameter is a template. */ | |
846 | OB_PUTC ('z'); | |
847 | build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); | |
848 | } | |
849 | else | |
59e621fc MM |
850 | /* It's a PARM_DECL. */ |
851 | build_mangled_name_for_type (TREE_TYPE (parm)); | |
73b0fce8 KL |
852 | } |
853 | } | |
854 | ||
855 | ||
386b8a85 JM |
856 | /* Add encodings for the vector of template parameters in PARMLIST, |
857 | given the vector of arguments to be substituted in ARGLIST. */ | |
858 | ||
4966381a | 859 | static void |
386b8a85 JM |
860 | build_template_parm_names (parmlist, arglist) |
861 | tree parmlist; | |
862 | tree arglist; | |
863 | { | |
864 | int i, nparms; | |
865 | ||
866 | nparms = TREE_VEC_LENGTH (parmlist); | |
867 | icat (nparms); | |
868 | for (i = 0; i < nparms; i++) | |
869 | { | |
870 | tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); | |
871 | tree arg = TREE_VEC_ELT (arglist, i); | |
872 | if (TREE_CODE (parm) == TYPE_DECL) | |
873 | { | |
874 | /* This parameter is a type. */ | |
875 | OB_PUTC ('Z'); | |
59e621fc | 876 | build_mangled_name_for_type (arg); |
386b8a85 | 877 | } |
73b0fce8 KL |
878 | else if (TREE_CODE (parm) == TEMPLATE_DECL) |
879 | { | |
880 | /* This parameter is a template. */ | |
881 | if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) | |
882 | /* Output parameter declaration, argument index and level */ | |
59e621fc | 883 | build_mangled_name_for_type (arg); |
73b0fce8 KL |
884 | else |
885 | { | |
886 | /* A TEMPLATE_DECL node, output the parameter declaration | |
887 | and template name */ | |
888 | ||
889 | OB_PUTC ('z'); | |
890 | build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (parm)); | |
891 | icat (IDENTIFIER_LENGTH (DECL_NAME (arg))); | |
892 | OB_PUTID (DECL_NAME (arg)); | |
893 | } | |
894 | } | |
386b8a85 JM |
895 | else |
896 | { | |
f7d98d58 | 897 | parm = tsubst (parm, arglist, NULL_TREE); |
386b8a85 | 898 | /* It's a PARM_DECL. */ |
59e621fc | 899 | build_mangled_name_for_type (TREE_TYPE (parm)); |
386b8a85 JM |
900 | build_overload_value (parm, arg, uses_template_parms (arglist)); |
901 | } | |
902 | } | |
903 | } | |
904 | ||
59e621fc MM |
905 | /* Output the representation for NAME, which is either a TYPE_DECL or |
906 | an IDENTIFIER. */ | |
386b8a85 | 907 | |
8d08fdba MS |
908 | static void |
909 | build_overload_identifier (name) | |
910 | tree name; | |
911 | { | |
5566b478 MS |
912 | if (TREE_CODE (name) == TYPE_DECL |
913 | && IS_AGGR_TYPE (TREE_TYPE (name)) | |
914 | && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)) | |
e1467ff2 MM |
915 | && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name))) |
916 | || (TREE_CODE (DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE | |
917 | (TREE_TYPE (name)))) | |
918 | == FUNCTION_DECL))) | |
8d08fdba | 919 | { |
59e621fc | 920 | /* NAME is the TYPE_DECL for a template specialization. */ |
8d08fdba | 921 | tree template, parmlist, arglist, tname; |
5566b478 | 922 | template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); |
36a117a5 | 923 | arglist = innermost_args (TREE_VALUE (template)); |
8d08fdba MS |
924 | template = TREE_PURPOSE (template); |
925 | tname = DECL_NAME (template); | |
98c1c668 | 926 | parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); |
8d08fdba MS |
927 | OB_PUTC ('t'); |
928 | icat (IDENTIFIER_LENGTH (tname)); | |
929 | OB_PUTID (tname); | |
386b8a85 | 930 | build_template_parm_names (parmlist, arglist); |
8d08fdba MS |
931 | } |
932 | else | |
933 | { | |
5566b478 MS |
934 | if (TREE_CODE (name) == TYPE_DECL) |
935 | name = DECL_NAME (name); | |
8cb9cd5d | 936 | if (numeric_output_need_bar) |
f376e137 MS |
937 | { |
938 | OB_PUTC ('_'); | |
8cb9cd5d | 939 | numeric_output_need_bar = 0; |
f376e137 | 940 | } |
8d08fdba MS |
941 | icat (IDENTIFIER_LENGTH (name)); |
942 | OB_PUTID (name); | |
943 | } | |
944 | } | |
945 | ||
42976354 | 946 | /* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce |
ed22c95e | 947 | the mangling for it. Used by build_mangled_name and build_static_name. */ |
42976354 BK |
948 | |
949 | static void | |
950 | build_qualified_name (decl) | |
951 | tree decl; | |
952 | { | |
953 | tree context; | |
954 | int i = 1; | |
955 | ||
956 | if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't') | |
957 | decl = TYPE_NAME (decl); | |
958 | ||
959 | /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ | |
960 | if (TREE_CODE (decl) == TYPE_DECL | |
ed22c95e | 961 | && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !flag_do_squangling) |
42976354 | 962 | { |
050367a3 MM |
963 | tree id = DECL_ASSEMBLER_NAME (decl); |
964 | OB_PUTID (id); | |
faa25e97 | 965 | if (ISDIGIT (IDENTIFIER_POINTER (id) [IDENTIFIER_LENGTH (id) - 1])) |
050367a3 | 966 | numeric_output_need_bar = 1; |
42976354 BK |
967 | return; |
968 | } | |
969 | ||
970 | context = decl; | |
ed22c95e AM |
971 | /* if we can't find a Ktype, do it the hard way */ |
972 | if (check_ktype (context, FALSE) == -1) | |
30394414 | 973 | { |
2c73f9f5 ML |
974 | /* count type and namespace scopes */ |
975 | while (DECL_CONTEXT (context) && DECL_CONTEXT (context) != global_namespace) | |
30394414 JM |
976 | { |
977 | i += 1; | |
978 | context = DECL_CONTEXT (context); | |
979 | if (check_ktype (context, FALSE) != -1) /* found it! */ | |
980 | break; | |
981 | if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') | |
982 | context = TYPE_NAME (context); | |
983 | } | |
30394414 | 984 | } |
42976354 BK |
985 | |
986 | if (i > 1) | |
987 | { | |
988 | OB_PUTC ('Q'); | |
050367a3 | 989 | build_underscore_int (i); |
42976354 BK |
990 | numeric_output_need_bar = 0; |
991 | } | |
992 | build_overload_nested_name (decl); | |
993 | } | |
994 | ||
59e621fc MM |
995 | /* Output the mangled representation for TYPE. If EXTRA_GCODE is |
996 | non-zero, mangled names for structure/union types are intentionally | |
997 | mangled differently from the method described in the ARM. */ | |
998 | ||
999 | void | |
1000 | build_mangled_name_for_type_with_Gcode (type, extra_Gcode) | |
1001 | tree type; | |
1002 | int extra_Gcode; | |
1003 | { | |
1004 | if (TYPE_PTRMEMFUNC_P (type)) | |
1005 | type = TYPE_PTRMEMFUNC_FN_TYPE (type); | |
53929c47 | 1006 | type = canonical_type_variant (type); |
59e621fc MM |
1007 | process_modifiers (type); |
1008 | process_overload_item (type, extra_Gcode); | |
1009 | } | |
1010 | ||
1011 | /* Like build_mangled_name_for_type_with_Gcode, but never outputs the | |
1012 | `G'. */ | |
1013 | ||
1014 | void | |
1015 | build_mangled_name_for_type (type) | |
1016 | tree type; | |
1017 | { | |
1018 | build_mangled_name_for_type_with_Gcode (type, 0); | |
1019 | } | |
1020 | ||
8d08fdba MS |
1021 | /* Given a list of parameters in PARMTYPES, create an unambiguous |
1022 | overload string. Should distinguish any type that C (or C++) can | |
1023 | distinguish. I.e., pointers to functions are treated correctly. | |
1024 | ||
1025 | Caller must deal with whether a final `e' goes on the end or not. | |
1026 | ||
1027 | Any default conversions must take place before this function | |
1028 | is called. | |
1029 | ||
1030 | BEGIN and END control initialization and finalization of the | |
1031 | obstack where we build the string. */ | |
1032 | ||
1033 | char * | |
1034 | build_overload_name (parmtypes, begin, end) | |
1035 | tree parmtypes; | |
1036 | int begin, end; | |
1037 | { | |
ed22c95e AM |
1038 | char *ret; |
1039 | start_squangling (); | |
1040 | ret = build_mangled_name (parmtypes, begin, end); | |
1041 | end_squangling (); | |
1042 | return ret ; | |
1043 | } | |
1044 | ||
59e621fc MM |
1045 | /* Output the mangled representation for PARMTYPES. If PARMTYPES is a |
1046 | TREE_LIST, then it is a list of parameter types. Otherwise, | |
1047 | PARMTYPES must be a single type. */ | |
1048 | ||
ed22c95e AM |
1049 | static char * |
1050 | build_mangled_name (parmtypes, begin, end) | |
1051 | tree parmtypes; | |
1052 | int begin, end; | |
1053 | { | |
ed22c95e AM |
1054 | if (begin) |
1055 | OB_INIT (); | |
8d08fdba | 1056 | |
59e621fc MM |
1057 | if (TREE_CODE (parmtypes) != TREE_LIST) |
1058 | /* There is only one type. */ | |
1059 | build_mangled_name_for_type (parmtypes); | |
1060 | else | |
8d08fdba | 1061 | { |
59e621fc MM |
1062 | /* There are several types in a parameter list. */ |
1063 | int nrepeats = 0; | |
1064 | int old_style_repeats = !flag_do_squangling && !nofold && typevec; | |
1065 | tree last_type = NULL_TREE; | |
1066 | ||
1067 | for (; parmtypes && parmtypes != void_list_node; | |
1068 | parmtypes = TREE_CHAIN (parmtypes)) | |
1069 | { | |
53929c47 | 1070 | tree parmtype = canonical_type_variant (TREE_VALUE (parmtypes)); |
59e621fc MM |
1071 | |
1072 | if (old_style_repeats) | |
1073 | { | |
1074 | /* Every argument gets counted. */ | |
2c73f9f5 | 1075 | my_friendly_assert (maxtype < typevec_size, 387); |
59e621fc MM |
1076 | typevec[maxtype++] = parmtype; |
1077 | } | |
ed22c95e | 1078 | |
59e621fc MM |
1079 | if (parmtype == last_type) |
1080 | { | |
1081 | if (flag_do_squangling | |
1082 | || (old_style_repeats && TREE_USED (parmtype) | |
1083 | && !TYPE_FOR_JAVA (parmtype))) | |
1084 | { | |
1085 | /* The next type is the same as this one. Keep | |
1086 | track of the repetition, and output the repeat | |
1087 | count later. */ | |
1088 | nrepeats++; | |
1089 | continue; | |
1090 | } | |
1091 | } | |
1092 | else if (nrepeats != 0) | |
1093 | { | |
1094 | /* Indicate how many times the previous parameter was | |
1095 | repeated. */ | |
1096 | if (old_style_repeats) | |
1097 | flush_repeats (nrepeats, last_type); | |
1098 | else | |
1099 | issue_nrepeats (nrepeats, last_type); | |
1100 | nrepeats = 0; | |
1101 | } | |
1102 | ||
1103 | last_type = parmtype; | |
ed22c95e | 1104 | |
59e621fc MM |
1105 | if (old_style_repeats) |
1106 | { | |
1107 | if (nrepeats) | |
1108 | { | |
1109 | flush_repeats (nrepeats, last_type); | |
1110 | nrepeats = 0; | |
1111 | } | |
ed22c95e | 1112 | |
59e621fc MM |
1113 | if (TREE_USED (parmtype)) |
1114 | { | |
acde952d | 1115 | #if 0 |
59e621fc MM |
1116 | /* We can turn this on at some point when we want |
1117 | improved symbol mangling. */ | |
1118 | nrepeats++; | |
acde952d | 1119 | #else |
59e621fc MM |
1120 | /* This is bug compatible with 2.7.x */ |
1121 | flush_repeats (nrepeats, parmtype); | |
d09ae635 | 1122 | #endif |
59e621fc MM |
1123 | nrepeats = 0; |
1124 | continue; | |
1125 | } | |
1126 | ||
1127 | /* Only cache types which take more than one character. */ | |
1128 | if ((parmtype != TYPE_MAIN_VARIANT (parmtype) | |
a1774733 BK |
1129 | || (TREE_CODE (parmtype) != INTEGER_TYPE |
1130 | && TREE_CODE (parmtype) != REAL_TYPE)) | |
ea419909 | 1131 | && ! TYPE_FOR_JAVA (parmtype)) |
59e621fc MM |
1132 | TREE_USED (parmtype) = 1; |
1133 | } | |
1134 | ||
1135 | /* Output the PARMTYPE. */ | |
1136 | build_mangled_name_for_type_with_Gcode (parmtype, 1); | |
1137 | } | |
1138 | ||
1139 | /* Output the repeat count for the last parameter, if | |
1140 | necessary. */ | |
1141 | if (nrepeats != 0) | |
1142 | { | |
1143 | if (old_style_repeats) | |
1144 | flush_repeats (nrepeats, last_type); | |
1145 | else | |
1146 | issue_nrepeats (nrepeats, last_type); | |
1147 | nrepeats = 0; | |
1148 | } | |
1149 | ||
1150 | if (!parmtypes) | |
1151 | /* The parameter list ends in an ellipsis. */ | |
1152 | OB_PUTC ('e'); | |
1153 | } | |
8d08fdba | 1154 | |
ed22c95e AM |
1155 | if (end) |
1156 | OB_FINISH (); | |
1157 | return (char *)obstack_base (&scratch_obstack); | |
1158 | } | |
8d08fdba | 1159 | |
ed22c95e AM |
1160 | /* handles emitting modifiers such as Constant, read-only, and volatile */ |
1161 | void | |
1162 | process_modifiers (parmtype) | |
1163 | tree parmtype; | |
1164 | { | |
ed22c95e AM |
1165 | if (TREE_READONLY (parmtype)) |
1166 | OB_PUTC ('C'); | |
a1774733 BK |
1167 | if (TREE_CODE (parmtype) == INTEGER_TYPE |
1168 | && (TYPE_MAIN_VARIANT (parmtype) | |
1169 | == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) | |
ea419909 | 1170 | && ! TYPE_FOR_JAVA (parmtype)) |
59e621fc | 1171 | OB_PUTC ('U'); |
ed22c95e AM |
1172 | if (TYPE_VOLATILE (parmtype)) |
1173 | OB_PUTC ('V'); | |
1174 | } | |
a5894242 | 1175 | |
59e621fc MM |
1176 | /* Check to see if TYPE has been entered into the Bcode typelist. If |
1177 | so, return 1 and emit a backreference to TYPE. Otherwise, add TYPE | |
1178 | to the list of back-referenceable types and return 0. */ | |
1179 | ||
1180 | int | |
1181 | check_btype (type) | |
1182 | tree type; | |
ed22c95e AM |
1183 | { |
1184 | int x; | |
a5894242 | 1185 | |
ed22c95e AM |
1186 | if (btypelist == NULL) |
1187 | return 0; | |
8d08fdba | 1188 | |
59e621fc MM |
1189 | if (!is_back_referenceable_type (type)) |
1190 | return 0; | |
31bebb60 | 1191 | |
59e621fc MM |
1192 | /* We assume that our caller has put out any necessary |
1193 | qualifiers. */ | |
1194 | type = TYPE_MAIN_VARIANT (type); | |
8d08fdba | 1195 | |
ed22c95e | 1196 | for (x = 0; x < maxbtype; x++) |
59e621fc MM |
1197 | if (type == btypelist[x]) |
1198 | { | |
1199 | OB_PUTC ('B'); | |
1200 | icat (x); | |
1201 | if (x > 9) | |
1202 | OB_PUTC ('_'); | |
1203 | return 1 ; | |
1204 | } | |
1205 | ||
ed22c95e AM |
1206 | if (maxbsize <= maxbtype) |
1207 | { | |
59e621fc | 1208 | /* Enlarge the table. */ |
ed22c95e | 1209 | maxbsize = maxbsize * 3 / 2; |
e06e4d45 | 1210 | btypelist = (tree *)xrealloc (btypelist, sizeof (tree) * maxbsize); |
ed22c95e | 1211 | } |
59e621fc MM |
1212 | |
1213 | /* Register the TYPE. */ | |
1214 | btypelist[maxbtype++] = type; | |
1215 | ||
ed22c95e AM |
1216 | return 0; |
1217 | } | |
8d08fdba | 1218 | |
ed22c95e AM |
1219 | /* handle emitting the correct code for various node types */ |
1220 | static void | |
1221 | process_overload_item (parmtype, extra_Gcode) | |
1222 | tree parmtype; | |
1223 | int extra_Gcode; | |
1224 | { | |
59e621fc | 1225 | numeric_output_need_bar = 0; |
8d08fdba | 1226 | |
ed22c95e AM |
1227 | /* These tree types are considered modifiers for B code squangling , */ |
1228 | /* and therefore should not get entries in the Btypelist */ | |
1229 | /* they are, however, repeatable types */ | |
8d08fdba | 1230 | |
ed22c95e AM |
1231 | switch (TREE_CODE (parmtype)) |
1232 | { | |
1233 | case REFERENCE_TYPE: | |
1234 | OB_PUTC ('R'); | |
1235 | goto more; | |
8d08fdba | 1236 | |
ed22c95e AM |
1237 | case ARRAY_TYPE: |
1238 | #if PARM_CAN_BE_ARRAY_TYPE | |
1239 | { | |
1240 | tree length; | |
1241 | ||
1242 | OB_PUTC ('A'); | |
1243 | if (TYPE_DOMAIN (parmtype) == NULL_TREE) | |
1244 | error("pointer/reference to array of unknown bound in parm type"); | |
1245 | else | |
53929c47 JM |
1246 | { |
1247 | tree length = array_type_nelts (parmtype); | |
1248 | if (TREE_CODE (length) != INTEGER_CST || flag_do_squangling) | |
1249 | { | |
1250 | length = fold (build (PLUS_EXPR, TREE_TYPE (length), | |
1251 | length, integer_one_node)); | |
1252 | STRIP_NOPS (length); | |
1253 | } | |
1254 | build_overload_value (sizetype, length, 1); | |
1255 | } | |
1256 | if (numeric_output_need_bar && ! flag_do_squangling) | |
1257 | OB_PUTC ('_'); | |
ed22c95e AM |
1258 | goto more; |
1259 | } | |
8d08fdba | 1260 | #else |
ed22c95e AM |
1261 | OB_PUTC ('P'); |
1262 | goto more; | |
8d08fdba MS |
1263 | #endif |
1264 | ||
ed22c95e AM |
1265 | case POINTER_TYPE: |
1266 | OB_PUTC ('P'); | |
1267 | more: | |
59e621fc | 1268 | build_mangled_name_for_type (TREE_TYPE (parmtype)); |
ed22c95e AM |
1269 | return; |
1270 | break; | |
31bebb60 KG |
1271 | |
1272 | default: | |
1273 | break; | |
ed22c95e AM |
1274 | } |
1275 | ||
59e621fc MM |
1276 | if (flag_do_squangling && check_btype (parmtype)) |
1277 | /* If PARMTYPE is already in the list of back-referenceable types, | |
1278 | then check_btype will output the appropriate reference, and | |
1279 | there's nothing more to do. */ | |
1280 | return; | |
8d08fdba | 1281 | |
ed22c95e AM |
1282 | switch (TREE_CODE (parmtype)) |
1283 | { | |
1284 | case OFFSET_TYPE: | |
1285 | OB_PUTC ('O'); | |
59e621fc | 1286 | build_mangled_name_for_type (TYPE_OFFSET_BASETYPE (parmtype)); |
ed22c95e | 1287 | OB_PUTC ('_'); |
59e621fc | 1288 | build_mangled_name_for_type (TREE_TYPE (parmtype)); |
ed22c95e | 1289 | break; |
8d08fdba | 1290 | |
ed22c95e AM |
1291 | case FUNCTION_TYPE: |
1292 | case METHOD_TYPE: | |
1293 | { | |
59e621fc | 1294 | tree parms = TYPE_ARG_TYPES (parmtype); |
ed22c95e | 1295 | |
59e621fc MM |
1296 | /* Rather than implementing a reentrant TYPEVEC, we turn off |
1297 | repeat codes here, unless we're squangling. Squangling | |
1298 | doesn't make use of the TYPEVEC, so there's no reentrancy | |
1299 | problem. */ | |
1300 | int old_nofold = nofold; | |
1301 | if (!flag_do_squangling) | |
1302 | nofold = 1; | |
1303 | ||
1304 | if (TREE_CODE (parmtype) == METHOD_TYPE) | |
1305 | { | |
1306 | /* Mark this as a method. */ | |
ed22c95e | 1307 | OB_PUTC ('M'); |
59e621fc MM |
1308 | /* Output the class of which this method is a member. */ |
1309 | build_mangled_name_for_type (TYPE_METHOD_BASETYPE (parmtype)); | |
1310 | /* Output any qualifiers for the `this' parameter. */ | |
1311 | process_modifiers (TREE_TYPE (TREE_VALUE (parms))); | |
1312 | } | |
ed22c95e | 1313 | |
59e621fc MM |
1314 | /* Output the parameter types. */ |
1315 | OB_PUTC ('F'); | |
1316 | if (parms == NULL_TREE) | |
1317 | OB_PUTC ('e'); | |
1318 | else if (parms == void_list_node) | |
1319 | OB_PUTC ('v'); | |
1320 | else | |
1321 | build_mangled_name (parms, 0, 0); | |
1322 | ||
1323 | /* Output the return type. */ | |
ed22c95e | 1324 | OB_PUTC ('_'); |
59e621fc MM |
1325 | build_mangled_name_for_type (TREE_TYPE (parmtype)); |
1326 | ||
ed22c95e AM |
1327 | nofold = old_nofold; |
1328 | break; | |
1329 | } | |
8d08fdba | 1330 | |
ed22c95e AM |
1331 | case INTEGER_TYPE: |
1332 | parmtype = TYPE_MAIN_VARIANT (parmtype); | |
1333 | if (parmtype == integer_type_node | |
ea419909 PB |
1334 | || parmtype == unsigned_type_node |
1335 | || parmtype == java_int_type_node) | |
ed22c95e AM |
1336 | OB_PUTC ('i'); |
1337 | else if (parmtype == long_integer_type_node | |
1338 | || parmtype == long_unsigned_type_node) | |
1339 | OB_PUTC ('l'); | |
1340 | else if (parmtype == short_integer_type_node | |
ea419909 PB |
1341 | || parmtype == short_unsigned_type_node |
1342 | || parmtype == java_short_type_node) | |
ed22c95e AM |
1343 | OB_PUTC ('s'); |
1344 | else if (parmtype == signed_char_type_node) | |
1345 | { | |
1346 | OB_PUTC ('S'); | |
1347 | OB_PUTC ('c'); | |
1348 | } | |
1349 | else if (parmtype == char_type_node | |
ea419909 PB |
1350 | || parmtype == unsigned_char_type_node |
1351 | || parmtype == java_byte_type_node) | |
ed22c95e | 1352 | OB_PUTC ('c'); |
ea419909 PB |
1353 | else if (parmtype == wchar_type_node |
1354 | || parmtype == java_char_type_node) | |
ed22c95e AM |
1355 | OB_PUTC ('w'); |
1356 | else if (parmtype == long_long_integer_type_node | |
ea419909 PB |
1357 | || parmtype == long_long_unsigned_type_node |
1358 | || parmtype == java_long_type_node) | |
ed22c95e AM |
1359 | OB_PUTC ('x'); |
1360 | #if 0 | |
1361 | /* it would seem there is no way to enter these in source code, | |
1362 | yet. (mrs) */ | |
1363 | else if (parmtype == long_long_long_integer_type_node | |
1364 | || parmtype == long_long_long_unsigned_type_node) | |
1365 | OB_PUTC ('q'); | |
8d08fdba | 1366 | #endif |
ea419909 PB |
1367 | else if (parmtype == java_boolean_type_node) |
1368 | OB_PUTC ('b'); | |
ed22c95e AM |
1369 | else |
1370 | my_friendly_abort (73); | |
1371 | break; | |
42976354 | 1372 | |
ed22c95e AM |
1373 | case BOOLEAN_TYPE: |
1374 | OB_PUTC ('b'); | |
1375 | break; | |
8d08fdba | 1376 | |
ed22c95e AM |
1377 | case REAL_TYPE: |
1378 | parmtype = TYPE_MAIN_VARIANT (parmtype); | |
1379 | if (parmtype == long_double_type_node) | |
1380 | OB_PUTC ('r'); | |
ea419909 PB |
1381 | else if (parmtype == double_type_node |
1382 | || parmtype == java_double_type_node) | |
ed22c95e | 1383 | OB_PUTC ('d'); |
ea419909 PB |
1384 | else if (parmtype == float_type_node |
1385 | || parmtype == java_float_type_node) | |
ed22c95e AM |
1386 | OB_PUTC ('f'); |
1387 | else my_friendly_abort (74); | |
1388 | break; | |
1389 | ||
1390 | case COMPLEX_TYPE: | |
1391 | OB_PUTC ('J'); | |
59e621fc | 1392 | build_mangled_name_for_type (TREE_TYPE (parmtype)); |
ed22c95e AM |
1393 | break; |
1394 | ||
1395 | case VOID_TYPE: | |
1396 | OB_PUTC ('v'); | |
1397 | break; | |
1398 | ||
1399 | case ERROR_MARK: /* not right, but nothing is anyway */ | |
1400 | break; | |
1401 | ||
1402 | /* have to do these */ | |
1403 | case UNION_TYPE: | |
1404 | case RECORD_TYPE: | |
1405 | { | |
1406 | if (extra_Gcode) | |
1407 | OB_PUTC ('G'); /* make it look incompatible with AT&T */ | |
1408 | /* drop through into next case */ | |
1409 | } | |
1410 | case ENUMERAL_TYPE: | |
1411 | { | |
1412 | tree name = TYPE_NAME (parmtype); | |
73b0fce8 | 1413 | |
ed22c95e AM |
1414 | if (TREE_CODE (name) == IDENTIFIER_NODE) |
1415 | { | |
1416 | build_overload_identifier (TYPE_NAME (parmtype)); | |
1417 | break; | |
1418 | } | |
1419 | my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248); | |
73b0fce8 | 1420 | |
ed22c95e AM |
1421 | build_qualified_name (name); |
1422 | break; | |
1423 | } | |
8d08fdba | 1424 | |
ed22c95e AM |
1425 | case UNKNOWN_TYPE: |
1426 | /* This will take some work. */ | |
1427 | OB_PUTC ('?'); | |
1428 | break; | |
1429 | ||
1430 | case TEMPLATE_TEMPLATE_PARM: | |
1431 | /* Find and output the original template parameter | |
1432 | declaration. */ | |
1433 | if (CLASSTYPE_TEMPLATE_INFO (parmtype)) | |
1434 | { | |
f84b4be9 JM |
1435 | build_mangled_template_parm_index ("tzX", |
1436 | TEMPLATE_TYPE_PARM_INDEX | |
1437 | (parmtype)); | |
1438 | build_template_parm_names | |
1439 | (DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)), | |
1440 | CLASSTYPE_TI_ARGS (parmtype)); | |
ed22c95e AM |
1441 | } |
1442 | else | |
1443 | { | |
f84b4be9 JM |
1444 | build_mangled_template_parm_index ("ZzX", |
1445 | TEMPLATE_TYPE_PARM_INDEX | |
1446 | (parmtype)); | |
1447 | build_template_template_parm_names | |
1448 | (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype))); | |
ed22c95e AM |
1449 | } |
1450 | break; | |
1451 | ||
1452 | case TEMPLATE_TYPE_PARM: | |
f84b4be9 JM |
1453 | build_mangled_template_parm_index ("X", |
1454 | TEMPLATE_TYPE_PARM_INDEX | |
1455 | (parmtype)); | |
ed22c95e AM |
1456 | break; |
1457 | ||
1458 | case TYPENAME_TYPE: | |
1459 | /* When mangling the type of a function template whose | |
1460 | declaration looks like: | |
1461 | ||
1462 | template <class T> void foo(typename T::U) | |
1463 | ||
1464 | we have to mangle these. */ | |
1465 | build_qualified_name (parmtype); | |
1466 | break; | |
8d08fdba | 1467 | |
ed22c95e AM |
1468 | default: |
1469 | my_friendly_abort (75); | |
8d08fdba MS |
1470 | } |
1471 | ||
8d08fdba | 1472 | } |
f376e137 | 1473 | |
42976354 BK |
1474 | /* Produce the mangling for a variable named NAME in CONTEXT, which can |
1475 | be either a class TYPE or a FUNCTION_DECL. */ | |
1476 | ||
f376e137 | 1477 | tree |
42976354 BK |
1478 | build_static_name (context, name) |
1479 | tree context, name; | |
f376e137 | 1480 | { |
42976354 BK |
1481 | OB_INIT (); |
1482 | numeric_output_need_bar = 0; | |
ed22c95e | 1483 | start_squangling (); |
42976354 BK |
1484 | #ifdef JOINER |
1485 | OB_PUTC ('_'); | |
1486 | build_qualified_name (context); | |
1487 | OB_PUTC (JOINER); | |
1488 | #else | |
1489 | OB_PUTS ("__static_"); | |
1490 | build_qualified_name (context); | |
a6f02587 | 1491 | OB_PUTC ('_'); |
42976354 BK |
1492 | #endif |
1493 | OB_PUTID (name); | |
1494 | OB_FINISH (); | |
ed22c95e | 1495 | end_squangling (); |
42976354 BK |
1496 | |
1497 | return get_identifier ((char *)obstack_base (&scratch_obstack)); | |
1498 | } | |
8d08fdba | 1499 | \f |
36a117a5 MM |
1500 | /* FOR_METHOD should be 1 if the declaration in question is for a member |
1501 | of a class (including a static member) and 2 if the declaration is | |
1502 | for a constructor. */ | |
1503 | tree | |
386b8a85 JM |
1504 | build_decl_overload_real (dname, parms, ret_type, tparms, targs, |
1505 | for_method) | |
8d08fdba MS |
1506 | tree dname; |
1507 | tree parms; | |
386b8a85 JM |
1508 | tree ret_type; |
1509 | tree tparms; | |
1510 | tree targs; | |
8d08fdba MS |
1511 | int for_method; |
1512 | { | |
1513 | char *name = IDENTIFIER_POINTER (dname); | |
1514 | ||
a28e3c7f | 1515 | /* member operators new and delete look like methods at this point. */ |
047f64a3 JM |
1516 | if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST |
1517 | && TREE_CHAIN (parms) == void_list_node) | |
a28e3c7f | 1518 | { |
00595019 MS |
1519 | if (dname == ansi_opname[(int) DELETE_EXPR]) |
1520 | return get_identifier ("__builtin_delete"); | |
1521 | else if (dname == ansi_opname[(int) VEC_DELETE_EXPR]) | |
1522 | return get_identifier ("__builtin_vec_delete"); | |
047f64a3 JM |
1523 | if (dname == ansi_opname[(int) NEW_EXPR]) |
1524 | return get_identifier ("__builtin_new"); | |
1525 | else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) | |
1526 | return get_identifier ("__builtin_vec_new"); | |
a28e3c7f | 1527 | } |
8d08fdba | 1528 | |
ed22c95e | 1529 | start_squangling (); |
8d08fdba MS |
1530 | OB_INIT (); |
1531 | if (for_method != 2) | |
1532 | OB_PUTCP (name); | |
1533 | /* Otherwise, we can divine that this is a constructor, | |
1534 | and figure out its name without any extra encoding. */ | |
1535 | ||
1536 | OB_PUTC2 ('_', '_'); | |
386b8a85 JM |
1537 | |
1538 | if (tparms) | |
1539 | { | |
59e621fc | 1540 | OB_PUTC ('H'); |
386b8a85 JM |
1541 | build_template_parm_names (tparms, targs); |
1542 | OB_PUTC ('_'); | |
1543 | } | |
59e621fc MM |
1544 | else if (!for_method && current_namespace == global_namespace) |
1545 | /* XXX this works only if we call this in the same namespace | |
1546 | as the declaration. Unfortunately, we don't have the _DECL, | |
1547 | only its name */ | |
1548 | OB_PUTC ('F'); | |
26877584 JM |
1549 | |
1550 | if (!for_method && current_namespace != global_namespace) | |
59e621fc | 1551 | /* qualify with namespace */ |
30394414 JM |
1552 | build_qualified_name (current_namespace); |
1553 | ||
8d08fdba | 1554 | if (parms == NULL_TREE) |
386b8a85 | 1555 | OB_PUTC ('e'); |
8d08fdba | 1556 | else if (parms == void_list_node) |
386b8a85 | 1557 | OB_PUTC ('v'); |
8d08fdba MS |
1558 | else |
1559 | { | |
ed22c95e AM |
1560 | if (!flag_do_squangling) /* Allocate typevec array. */ |
1561 | { | |
1562 | maxtype = 0; | |
2c73f9f5 ML |
1563 | typevec_size = list_length (parms); |
1564 | if (!for_method && current_namespace != global_namespace) | |
1565 | /* the namespace of a global function needs one slot */ | |
1566 | typevec_size++; | |
1567 | typevec = (tree *)alloca (typevec_size * sizeof (tree)); | |
ed22c95e | 1568 | } |
8d08fdba | 1569 | nofold = 0; |
59e621fc | 1570 | |
8d08fdba MS |
1571 | if (for_method) |
1572 | { | |
59e621fc | 1573 | tree this_type = TREE_VALUE (parms); |
8d08fdba | 1574 | |
59e621fc MM |
1575 | if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ |
1576 | this_type = SIGNATURE_TYPE (this_type); | |
1577 | else | |
1578 | this_type = TREE_TYPE (this_type); | |
1579 | ||
1580 | build_mangled_name_for_type (this_type); | |
1581 | ||
1582 | if (!flag_do_squangling) | |
1583 | { | |
1584 | my_friendly_assert (maxtype < typevec_size, 387); | |
1585 | typevec[maxtype++] = this_type; | |
1586 | TREE_USED (this_type) = 1; | |
1587 | ||
1588 | /* By setting up PARMS in this way, the loop below will | |
1589 | automatically clear TREE_USED on THIS_TYPE. */ | |
1590 | parms = temp_tree_cons (NULL_TREE, this_type, | |
1591 | TREE_CHAIN (parms)); | |
1592 | } | |
8d08fdba MS |
1593 | |
1594 | if (TREE_CHAIN (parms)) | |
ed22c95e | 1595 | build_mangled_name (TREE_CHAIN (parms), 0, 0); |
8d08fdba | 1596 | else |
386b8a85 | 1597 | OB_PUTC ('e'); |
8d08fdba MS |
1598 | } |
1599 | else | |
30394414 JM |
1600 | { |
1601 | /* the namespace qualifier for a global function | |
1602 | will count as type */ | |
1603 | if (current_namespace != global_namespace | |
1604 | && !flag_do_squangling) | |
2c73f9f5 ML |
1605 | { |
1606 | my_friendly_assert (maxtype < typevec_size, 387); | |
1607 | typevec[maxtype++] = current_namespace; | |
1608 | } | |
30394414 JM |
1609 | build_mangled_name (parms, 0, 0); |
1610 | } | |
ed22c95e AM |
1611 | |
1612 | if (!flag_do_squangling) /* Deallocate typevec array */ | |
1613 | { | |
1614 | tree t = parms; | |
1615 | typevec = NULL; | |
1616 | while (t) | |
1617 | { | |
3474f462 AM |
1618 | tree temp = TREE_VALUE (t); |
1619 | TREE_USED (temp) = 0; | |
1620 | /* clear out the type variant in case we used it */ | |
53929c47 | 1621 | temp = canonical_type_variant (temp); |
3474f462 | 1622 | TREE_USED (temp) = 0; |
ed22c95e AM |
1623 | t = TREE_CHAIN (t); |
1624 | } | |
1625 | } | |
8d08fdba | 1626 | } |
386b8a85 | 1627 | |
1f06b267 | 1628 | if (ret_type != NULL_TREE && for_method != 2) |
386b8a85 JM |
1629 | { |
1630 | /* Add the return type. */ | |
1631 | OB_PUTC ('_'); | |
59e621fc | 1632 | build_mangled_name_for_type (ret_type); |
386b8a85 JM |
1633 | } |
1634 | ||
1635 | OB_FINISH (); | |
ed22c95e | 1636 | end_squangling (); |
8d08fdba MS |
1637 | { |
1638 | tree n = get_identifier (obstack_base (&scratch_obstack)); | |
1639 | if (IDENTIFIER_OPNAME_P (dname)) | |
1640 | IDENTIFIER_OPNAME_P (n) = 1; | |
1641 | return n; | |
1642 | } | |
1643 | } | |
1644 | ||
386b8a85 JM |
1645 | /* Change the name of a function definition so that it may be |
1646 | overloaded. NAME is the name of the function to overload, | |
1647 | PARMS is the parameter list (which determines what name the | |
1648 | final function obtains). | |
1649 | ||
1650 | FOR_METHOD is 1 if this overload is being performed | |
1651 | for a method, rather than a function type. It is 2 if | |
1652 | this overload is being performed for a constructor. */ | |
1653 | ||
1654 | tree | |
1655 | build_decl_overload (dname, parms, for_method) | |
1656 | tree dname; | |
1657 | tree parms; | |
1658 | int for_method; | |
1659 | { | |
1660 | return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE, | |
1661 | NULL_TREE, for_method); | |
1662 | } | |
1663 | ||
36a117a5 | 1664 | /* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ |
386b8a85 JM |
1665 | |
1666 | tree | |
36a117a5 | 1667 | set_mangled_name_for_decl (decl) |
9a68c51f | 1668 | tree decl; |
386b8a85 | 1669 | { |
36a117a5 | 1670 | tree parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
9a68c51f | 1671 | |
36a117a5 MM |
1672 | if (DECL_STATIC_FUNCTION_P (decl)) |
1673 | parm_types = | |
1674 | hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)), | |
1675 | parm_types); | |
1676 | else | |
1677 | /* The only member functions whose type is a FUNCTION_TYPE, rather | |
1678 | than a METHOD_TYPE, should be static members. */ | |
1679 | my_friendly_assert (!DECL_CONTEXT (decl) | |
1680 | || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl))) | |
1681 | || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE, | |
1682 | 0); | |
1683 | ||
1684 | DECL_ASSEMBLER_NAME (decl) | |
1685 | = build_decl_overload (DECL_NAME (decl), parm_types, | |
1686 | DECL_FUNCTION_MEMBER_P (decl) | |
1687 | + DECL_CONSTRUCTOR_P (decl)); | |
386b8a85 JM |
1688 | } |
1689 | ||
8d08fdba | 1690 | /* Build an overload name for the type expression TYPE. */ |
e92cc029 | 1691 | |
8d08fdba MS |
1692 | tree |
1693 | build_typename_overload (type) | |
1694 | tree type; | |
1695 | { | |
1696 | tree id; | |
1697 | ||
1698 | OB_INIT (); | |
1699 | OB_PUTID (ansi_opname[(int) TYPE_EXPR]); | |
1700 | nofold = 1; | |
ed22c95e AM |
1701 | start_squangling (); |
1702 | build_mangled_name (type, 0, 1); | |
8d08fdba MS |
1703 | id = get_identifier (obstack_base (&scratch_obstack)); |
1704 | IDENTIFIER_OPNAME_P (id) = 1; | |
a0a33927 | 1705 | #if 0 |
d2e5ee5c | 1706 | IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type); |
a0a33927 | 1707 | #endif |
51c184be | 1708 | TREE_TYPE (id) = type; |
ed22c95e | 1709 | end_squangling (); |
8d08fdba MS |
1710 | return id; |
1711 | } | |
1712 | ||
8d08fdba | 1713 | tree |
6b5fbb55 MS |
1714 | build_overload_with_type (name, type) |
1715 | tree name, type; | |
8d08fdba MS |
1716 | { |
1717 | OB_INIT (); | |
6b5fbb55 | 1718 | OB_PUTID (name); |
8d08fdba MS |
1719 | nofold = 1; |
1720 | ||
ed22c95e AM |
1721 | start_squangling (); |
1722 | build_mangled_name (type, 0, 1); | |
1723 | end_squangling (); | |
8d08fdba MS |
1724 | return get_identifier (obstack_base (&scratch_obstack)); |
1725 | } | |
1726 | ||
67d743fe MS |
1727 | tree |
1728 | get_id_2 (name, name2) | |
1729 | char *name; | |
1730 | tree name2; | |
1731 | { | |
1732 | OB_INIT (); | |
1733 | OB_PUTCP (name); | |
1734 | OB_PUTID (name2); | |
1735 | OB_FINISH (); | |
1736 | return get_identifier (obstack_base (&scratch_obstack)); | |
1737 | } | |
711734a9 JM |
1738 | |
1739 | /* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. */ | |
1740 | ||
1741 | tree | |
1742 | build_destructor_name (type) | |
1743 | tree type; | |
1744 | { | |
1745 | return build_overload_with_type (get_identifier (DESTRUCTOR_DECL_PREFIX), | |
1746 | type); | |
1747 | } | |
8d08fdba MS |
1748 | \f |
1749 | /* Given a tree_code CODE, and some arguments (at least one), | |
1750 | attempt to use an overloaded operator on the arguments. | |
1751 | ||
1752 | For unary operators, only the first argument need be checked. | |
1753 | For binary operators, both arguments may need to be checked. | |
1754 | ||
1755 | Member functions can convert class references to class pointers, | |
1756 | for one-level deep indirection. More than that is not supported. | |
1757 | Operators [](), ()(), and ->() must be member functions. | |
1758 | ||
1759 | We call function call building calls with LOOKUP_COMPLAIN if they | |
1760 | are our only hope. This is true when we see a vanilla operator | |
1761 | applied to something of aggregate type. If this fails, we are free | |
1762 | to return `error_mark_node', because we will have reported the | |
1763 | error. | |
1764 | ||
1765 | Operators NEW and DELETE overload in funny ways: operator new takes | |
1766 | a single `size' parameter, and operator delete takes a pointer to the | |
1767 | storage being deleted. When overloading these operators, success is | |
1768 | assumed. If there is a failure, report an error message and return | |
1769 | `error_mark_node'. */ | |
1770 | ||
1771 | /* NOSTRICT */ | |
1772 | tree | |
1773 | build_opfncall (code, flags, xarg1, xarg2, arg3) | |
1774 | enum tree_code code; | |
1775 | int flags; | |
1776 | tree xarg1, xarg2, arg3; | |
1777 | { | |
277294d7 | 1778 | return build_new_op (code, flags, xarg1, xarg2, arg3); |
8d08fdba MS |
1779 | } |
1780 | \f | |
1781 | /* This function takes an identifier, ID, and attempts to figure out what | |
1782 | it means. There are a number of possible scenarios, presented in increasing | |
1783 | order of hair: | |
1784 | ||
1785 | 1) not in a class's scope | |
1786 | 2) in class's scope, member name of the class's method | |
1787 | 3) in class's scope, but not a member name of the class | |
1788 | 4) in class's scope, member name of a class's variable | |
1789 | ||
1790 | NAME is $1 from the bison rule. It is an IDENTIFIER_NODE. | |
1791 | VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1) | |
8d08fdba MS |
1792 | |
1793 | As a last ditch, try to look up the name as a label and return that | |
1794 | address. | |
1795 | ||
1796 | Values which are declared as being of REFERENCE_TYPE are | |
1797 | automatically dereferenced here (as a hack to make the | |
1798 | compiler faster). */ | |
1799 | ||
1800 | tree | |
5566b478 | 1801 | hack_identifier (value, name) |
8d08fdba | 1802 | tree value, name; |
8d08fdba | 1803 | { |
de22184b | 1804 | tree type; |
8d08fdba | 1805 | |
bd6dd845 | 1806 | if (value == error_mark_node) |
8d08fdba MS |
1807 | { |
1808 | if (current_class_name) | |
1809 | { | |
1810 | tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1); | |
1811 | if (fields == error_mark_node) | |
1812 | return error_mark_node; | |
1813 | if (fields) | |
1814 | { | |
1815 | tree fndecl; | |
1816 | ||
1817 | fndecl = TREE_VALUE (fields); | |
1818 | my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251); | |
2c73f9f5 ML |
1819 | /* I could not trigger this code. MvL */ |
1820 | my_friendly_abort (980325); | |
1821 | #ifdef DEAD | |
8d08fdba MS |
1822 | if (DECL_CHAIN (fndecl) == NULL_TREE) |
1823 | { | |
1824 | warning ("methods cannot be converted to function pointers"); | |
1825 | return fndecl; | |
1826 | } | |
1827 | else | |
1828 | { | |
1829 | error ("ambiguous request for method pointer `%s'", | |
1830 | IDENTIFIER_POINTER (name)); | |
1831 | return error_mark_node; | |
1832 | } | |
2c73f9f5 | 1833 | #endif |
8d08fdba MS |
1834 | } |
1835 | } | |
1836 | if (flag_labels_ok && IDENTIFIER_LABEL_VALUE (name)) | |
1837 | { | |
1838 | return IDENTIFIER_LABEL_VALUE (name); | |
1839 | } | |
1840 | return error_mark_node; | |
1841 | } | |
1842 | ||
1843 | type = TREE_TYPE (value); | |
1844 | if (TREE_CODE (value) == FIELD_DECL) | |
1845 | { | |
4ac14744 | 1846 | if (current_class_ptr == NULL_TREE) |
8d08fdba MS |
1847 | { |
1848 | error ("request for member `%s' in static member function", | |
1849 | IDENTIFIER_POINTER (DECL_NAME (value))); | |
1850 | return error_mark_node; | |
1851 | } | |
4ac14744 | 1852 | TREE_USED (current_class_ptr) = 1; |
a5894242 | 1853 | |
8d08fdba MS |
1854 | /* Mark so that if we are in a constructor, and then find that |
1855 | this field was initialized by a base initializer, | |
1856 | we can emit an error message. */ | |
1857 | TREE_USED (value) = 1; | |
4ac14744 | 1858 | value = build_component_ref (current_class_ref, name, NULL_TREE, 1); |
8d08fdba | 1859 | } |
6b5fbb55 | 1860 | else if (really_overloaded_fn (value)) |
8d08fdba | 1861 | { |
72b7eeff | 1862 | #if 0 |
5b605f68 | 1863 | tree t = get_first_fn (value); |
eac293a1 | 1864 | for (; t; t = DECL_CHAIN (t)) |
8d08fdba | 1865 | { |
eac293a1 MS |
1866 | if (TREE_CODE (t) == TEMPLATE_DECL) |
1867 | continue; | |
1868 | ||
5b605f68 | 1869 | assemble_external (t); |
8d08fdba | 1870 | TREE_USED (t) = 1; |
8d08fdba | 1871 | } |
72b7eeff | 1872 | #endif |
8d08fdba | 1873 | } |
2c73f9f5 ML |
1874 | else if (TREE_CODE (value) == OVERLOAD) |
1875 | /* not really overloaded function */ | |
1876 | mark_used (OVL_FUNCTION (value)); | |
a5ef9010 JM |
1877 | else if (TREE_CODE (value) == TREE_LIST) |
1878 | { | |
72b7eeff | 1879 | /* Ambiguous reference to base members, possibly other cases?. */ |
a5ef9010 JM |
1880 | tree t = value; |
1881 | while (t && TREE_CODE (t) == TREE_LIST) | |
1882 | { | |
72b7eeff | 1883 | mark_used (TREE_VALUE (t)); |
a5ef9010 JM |
1884 | t = TREE_CHAIN (t); |
1885 | } | |
1886 | } | |
2c73f9f5 | 1887 | else if (TREE_CODE (value) == NAMESPACE_DECL) |
0e607f34 JM |
1888 | { |
1889 | cp_error ("use of namespace `%D' as expression", value); | |
1890 | return error_mark_node; | |
1891 | } | |
1892 | else if (DECL_CLASS_TEMPLATE_P (value)) | |
1893 | { | |
1894 | cp_error ("use of class template `%T' as expression", value); | |
1895 | return error_mark_node; | |
1896 | } | |
8d08fdba | 1897 | else |
72b7eeff | 1898 | mark_used (value); |
8d08fdba | 1899 | |
e76a2646 | 1900 | if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL) |
5566b478 MS |
1901 | { |
1902 | tree context = decl_function_context (value); | |
1903 | if (context != NULL_TREE && context != current_function_decl | |
1904 | && ! TREE_STATIC (value)) | |
1905 | { | |
e76a2646 | 1906 | cp_error ("use of %s from containing function", |
5566b478 MS |
1907 | (TREE_CODE (value) == VAR_DECL |
1908 | ? "`auto' variable" : "parameter")); | |
e76a2646 MS |
1909 | cp_error_at (" `%#D' declared here", value); |
1910 | value = error_mark_node; | |
5566b478 MS |
1911 | } |
1912 | } | |
1913 | ||
8d08fdba MS |
1914 | if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) |
1915 | { | |
1916 | if (DECL_LANG_SPECIFIC (value) | |
1917 | && DECL_CLASS_CONTEXT (value) != current_class_type) | |
1918 | { | |
be99da77 | 1919 | tree path, access; |
8d08fdba MS |
1920 | register tree context |
1921 | = (TREE_CODE (value) == FUNCTION_DECL && DECL_VIRTUAL_P (value)) | |
1922 | ? DECL_CLASS_CONTEXT (value) | |
1923 | : DECL_CONTEXT (value); | |
1924 | ||
1925 | get_base_distance (context, current_class_type, 0, &path); | |
1926 | if (path) | |
1927 | { | |
1928 | access = compute_access (path, value); | |
be99da77 | 1929 | if (access != access_public_node) |
8d08fdba MS |
1930 | { |
1931 | if (TREE_CODE (value) == VAR_DECL) | |
1932 | error ("static member `%s' is %s", | |
1933 | IDENTIFIER_POINTER (name), | |
beb53fb8 JM |
1934 | TREE_PRIVATE (value) ? "private" |
1935 | : "from a private base class"); | |
8d08fdba MS |
1936 | else |
1937 | error ("enum `%s' is from private base class", | |
1938 | IDENTIFIER_POINTER (name)); | |
1939 | return error_mark_node; | |
1940 | } | |
1941 | } | |
1942 | } | |
8d08fdba | 1943 | } |
7834ab39 | 1944 | else if (TREE_CODE (value) == TREE_LIST && TREE_NONLOCAL_FLAG (value)) |
8d08fdba MS |
1945 | { |
1946 | if (type == 0) | |
1947 | { | |
1948 | error ("request for member `%s' is ambiguous in multiple inheritance lattice", | |
1949 | IDENTIFIER_POINTER (name)); | |
1950 | return error_mark_node; | |
1951 | } | |
1952 | ||
1953 | return value; | |
1954 | } | |
1955 | ||
5156628f | 1956 | if (TREE_CODE (type) == REFERENCE_TYPE && ! processing_template_decl) |
6b5fbb55 | 1957 | value = convert_from_reference (value); |
8d08fdba MS |
1958 | return value; |
1959 | } | |
1960 | ||
8926095f | 1961 | \f |
8926095f MS |
1962 | tree |
1963 | make_thunk (function, delta) | |
1964 | tree function; | |
1965 | int delta; | |
1966 | { | |
b87692e5 | 1967 | tree thunk_id; |
8926095f | 1968 | tree thunk; |
8926095f | 1969 | tree func_decl; |
cc600f33 | 1970 | |
8926095f MS |
1971 | if (TREE_CODE (function) != ADDR_EXPR) |
1972 | abort (); | |
1973 | func_decl = TREE_OPERAND (function, 0); | |
1974 | if (TREE_CODE (func_decl) != FUNCTION_DECL) | |
1975 | abort (); | |
cc600f33 JM |
1976 | |
1977 | OB_INIT (); | |
1978 | OB_PUTS ("__thunk_"); | |
1979 | if (delta > 0) | |
1980 | { | |
1981 | OB_PUTC ('n'); | |
1982 | icat (delta); | |
1983 | } | |
5edb8b93 | 1984 | else |
cc600f33 JM |
1985 | icat (-delta); |
1986 | OB_PUTC ('_'); | |
1987 | OB_PUTID (DECL_ASSEMBLER_NAME (func_decl)); | |
1988 | OB_FINISH (); | |
1989 | thunk_id = get_identifier (obstack_base (&scratch_obstack)); | |
1990 | ||
a0a33927 MS |
1991 | thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); |
1992 | if (thunk && TREE_CODE (thunk) != THUNK_DECL) | |
1993 | { | |
fc378698 | 1994 | cp_error ("implementation-reserved name `%D' used", thunk_id); |
2c73f9f5 ML |
1995 | thunk = NULL_TREE; |
1996 | SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); | |
a0a33927 MS |
1997 | } |
1998 | if (thunk == NULL_TREE) | |
1999 | { | |
eb448459 MS |
2000 | thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); |
2001 | TREE_READONLY (thunk) = TREE_READONLY (func_decl); | |
2002 | TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); | |
7fcdf4c2 | 2003 | comdat_linkage (thunk); |
72b7eeff | 2004 | TREE_SET_CODE (thunk, THUNK_DECL); |
a0a33927 MS |
2005 | DECL_INITIAL (thunk) = function; |
2006 | THUNK_DELTA (thunk) = delta; | |
72b7eeff | 2007 | DECL_EXTERNAL (thunk) = 1; |
eb448459 | 2008 | DECL_ARTIFICIAL (thunk) = 1; |
a0a33927 MS |
2009 | /* So that finish_file can write out any thunks that need to be: */ |
2010 | pushdecl_top_level (thunk); | |
2011 | } | |
8926095f MS |
2012 | return thunk; |
2013 | } | |
2014 | ||
eb448459 MS |
2015 | /* Emit the definition of a C++ multiple inheritance vtable thunk. */ |
2016 | ||
8926095f MS |
2017 | void |
2018 | emit_thunk (thunk_fndecl) | |
824b9a4c | 2019 | tree thunk_fndecl; |
8926095f | 2020 | { |
8926095f MS |
2021 | tree function = TREE_OPERAND (DECL_INITIAL (thunk_fndecl), 0); |
2022 | int delta = THUNK_DELTA (thunk_fndecl); | |
8926095f MS |
2023 | |
2024 | if (TREE_ASM_WRITTEN (thunk_fndecl)) | |
2025 | return; | |
2026 | ||
a0a33927 MS |
2027 | TREE_ASM_WRITTEN (thunk_fndecl) = 1; |
2028 | ||
809c8c30 JM |
2029 | TREE_ADDRESSABLE (function) = 1; |
2030 | mark_used (function); | |
2031 | ||
8926095f MS |
2032 | if (current_function_decl) |
2033 | abort (); | |
a0128b67 MS |
2034 | |
2035 | TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL); | |
eb66be0e | 2036 | |
eb448459 | 2037 | { |
a80e4195 | 2038 | #ifdef ASM_OUTPUT_MI_THUNK |
eb448459 MS |
2039 | char *fnname; |
2040 | current_function_decl = thunk_fndecl; | |
b87692e5 MS |
2041 | /* Make sure we build up its RTL before we go onto the |
2042 | temporary obstack. */ | |
2043 | make_function_rtl (thunk_fndecl); | |
eb448459 MS |
2044 | temporary_allocation (); |
2045 | DECL_RESULT (thunk_fndecl) | |
2046 | = build_decl (RESULT_DECL, 0, integer_type_node); | |
eb448459 | 2047 | fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); |
da20811c | 2048 | init_function_start (thunk_fndecl, input_filename, lineno); |
ed48174c | 2049 | current_function_is_thunk = 1; |
eb448459 MS |
2050 | assemble_start_function (thunk_fndecl, fnname); |
2051 | ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function); | |
2052 | assemble_end_function (thunk_fndecl, fnname); | |
2053 | permanent_allocation (1); | |
2054 | current_function_decl = 0; | |
eb66be0e | 2055 | #else /* ASM_OUTPUT_MI_THUNK */ |
eb448459 MS |
2056 | /* If we don't have the necessary macro for efficient thunks, generate a |
2057 | thunk function that just makes a call to the real function. | |
2058 | Unfortunately, this doesn't work for varargs. */ | |
2059 | ||
eb66be0e | 2060 | tree a, t; |
8926095f | 2061 | |
eb448459 MS |
2062 | if (varargs_function_p (function)) |
2063 | cp_error ("generic thunk code fails for method `%#D' which uses `...'", | |
2064 | function); | |
2065 | ||
eb66be0e MS |
2066 | /* Set up clone argument trees for the thunk. */ |
2067 | t = NULL_TREE; | |
2068 | for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) | |
2069 | { | |
2070 | tree x = copy_node (a); | |
2071 | TREE_CHAIN (x) = t; | |
2072 | DECL_CONTEXT (x) = thunk_fndecl; | |
2073 | t = x; | |
2074 | } | |
2075 | a = nreverse (t); | |
2076 | DECL_ARGUMENTS (thunk_fndecl) = a; | |
2077 | DECL_RESULT (thunk_fndecl) = NULL_TREE; | |
eb448459 MS |
2078 | DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function); |
2079 | copy_lang_decl (thunk_fndecl); | |
2080 | DECL_INTERFACE_KNOWN (thunk_fndecl) = 1; | |
2081 | DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1; | |
eb66be0e MS |
2082 | |
2083 | start_function (NULL_TREE, thunk_fndecl, NULL_TREE, 1); | |
2084 | store_parm_decls (); | |
eb448459 | 2085 | current_function_is_thunk = 1; |
eb66be0e MS |
2086 | |
2087 | /* Build up the call to the real function. */ | |
2088 | t = build_int_2 (delta, -1 * (delta < 0)); | |
2089 | TREE_TYPE (t) = signed_type (sizetype); | |
2090 | t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t)); | |
e66d884e | 2091 | t = expr_tree_cons (NULL_TREE, t, NULL_TREE); |
eb66be0e | 2092 | for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) |
e66d884e | 2093 | t = expr_tree_cons (NULL_TREE, a, t); |
eb66be0e MS |
2094 | t = nreverse (t); |
2095 | t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); | |
2096 | c_expand_return (t); | |
2097 | ||
2098 | finish_function (lineno, 0, 0); | |
4d6efa25 JM |
2099 | |
2100 | /* Don't let the backend defer this function. */ | |
2101 | if (DECL_DEFER_OUTPUT (thunk_fndecl)) | |
2102 | { | |
2103 | output_inline_function (thunk_fndecl); | |
2104 | permanent_allocation (1); | |
2105 | } | |
809c8c30 | 2106 | #endif /* ASM_OUTPUT_MI_THUNK */ |
eb448459 | 2107 | } |
8926095f | 2108 | |
eb66be0e | 2109 | TREE_SET_CODE (thunk_fndecl, THUNK_DECL); |
8926095f | 2110 | } |
f376e137 MS |
2111 | \f |
2112 | /* Code for synthesizing methods which have default semantics defined. */ | |
2113 | ||
0171aeab JM |
2114 | /* For the anonymous union in TYPE, return the member that is at least as |
2115 | large as the rest of the members, so we can copy it. */ | |
e92cc029 | 2116 | |
0171aeab JM |
2117 | static tree |
2118 | largest_union_member (type) | |
2119 | tree type; | |
2120 | { | |
2121 | tree f, type_size = TYPE_SIZE (type); | |
2122 | ||
2123 | for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f)) | |
14ac3bfe | 2124 | if (simple_cst_equal (DECL_SIZE (f), type_size) == 1) |
0171aeab JM |
2125 | return f; |
2126 | ||
2127 | /* We should always find one. */ | |
2128 | my_friendly_abort (323); | |
2129 | return NULL_TREE; | |
2130 | } | |
2131 | ||
f376e137 | 2132 | /* Generate code for default X(X&) constructor. */ |
e92cc029 | 2133 | |
824b9a4c | 2134 | static void |
db5ae43f | 2135 | do_build_copy_constructor (fndecl) |
f376e137 MS |
2136 | tree fndecl; |
2137 | { | |
2138 | tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); | |
2139 | tree t; | |
2140 | ||
f376e137 MS |
2141 | clear_last_expr (); |
2142 | push_momentary (); | |
2143 | ||
2144 | if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) | |
2145 | parm = TREE_CHAIN (parm); | |
2146 | parm = convert_from_reference (parm); | |
2147 | ||
a59ca936 JM |
2148 | if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) |
2149 | && is_empty_class (current_class_type)) | |
2150 | /* Don't copy the padding byte; it might not have been allocated | |
2151 | if *this is a base subobject. */; | |
2152 | else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) | |
f376e137 | 2153 | { |
4ac14744 | 2154 | t = build (INIT_EXPR, void_type_node, current_class_ref, parm); |
f376e137 MS |
2155 | TREE_SIDE_EFFECTS (t) = 1; |
2156 | cplus_expand_expr_stmt (t); | |
2157 | } | |
2158 | else | |
2159 | { | |
2160 | tree fields = TYPE_FIELDS (current_class_type); | |
2161 | int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); | |
2162 | tree binfos = TYPE_BINFO_BASETYPES (current_class_type); | |
2163 | int i; | |
2164 | ||
2165 | for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; | |
2166 | t = TREE_CHAIN (t)) | |
2167 | { | |
2168 | tree basetype = BINFO_TYPE (t); | |
8ccc31eb MS |
2169 | tree p = convert_to_reference |
2170 | (build_reference_type (basetype), parm, | |
2171 | CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); | |
f376e137 | 2172 | p = convert_from_reference (p); |
e349ee73 MS |
2173 | |
2174 | if (p == error_mark_node) | |
2175 | cp_error ("in default copy constructor"); | |
2176 | else | |
2177 | current_base_init_list = tree_cons (basetype, | |
2178 | p, current_base_init_list); | |
f376e137 MS |
2179 | } |
2180 | ||
2181 | for (i = 0; i < n_bases; ++i) | |
2182 | { | |
2183 | tree p, basetype = TREE_VEC_ELT (binfos, i); | |
2184 | if (TREE_VIA_VIRTUAL (basetype)) | |
8ccc31eb | 2185 | continue; |
f376e137 MS |
2186 | |
2187 | basetype = BINFO_TYPE (basetype); | |
8ccc31eb MS |
2188 | p = convert_to_reference |
2189 | (build_reference_type (basetype), parm, | |
2190 | CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); | |
e349ee73 MS |
2191 | |
2192 | if (p == error_mark_node) | |
2193 | cp_error ("in default copy constructor"); | |
2194 | else | |
2195 | { | |
2196 | p = convert_from_reference (p); | |
2197 | current_base_init_list = tree_cons (basetype, | |
2198 | p, current_base_init_list); | |
2199 | } | |
f376e137 MS |
2200 | } |
2201 | for (; fields; fields = TREE_CHAIN (fields)) | |
2202 | { | |
de22184b | 2203 | tree init, t; |
a5894242 MS |
2204 | tree field = fields; |
2205 | ||
2206 | if (TREE_CODE (field) != FIELD_DECL) | |
f376e137 | 2207 | continue; |
8dff1027 MS |
2208 | |
2209 | init = parm; | |
a5894242 | 2210 | if (DECL_NAME (field)) |
f376e137 | 2211 | { |
a5894242 | 2212 | if (VFIELD_NAME_P (DECL_NAME (field))) |
f376e137 | 2213 | continue; |
a5894242 | 2214 | if (VBASE_NAME_P (DECL_NAME (field))) |
f376e137 MS |
2215 | continue; |
2216 | ||
2217 | /* True for duplicate members. */ | |
a5894242 | 2218 | if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) |
f376e137 MS |
2219 | continue; |
2220 | } | |
a5894242 | 2221 | else if ((t = TREE_TYPE (field)) != NULL_TREE |
67ffc812 | 2222 | && ANON_UNION_TYPE_P (t) |
0171aeab | 2223 | && TYPE_FIELDS (t) != NULL_TREE) |
8dff1027 MS |
2224 | { |
2225 | do | |
2226 | { | |
2227 | init = build (COMPONENT_REF, t, init, field); | |
2228 | field = largest_union_member (t); | |
2229 | } | |
2230 | while ((t = TREE_TYPE (field)) != NULL_TREE | |
67ffc812 | 2231 | && ANON_UNION_TYPE_P (t) |
8dff1027 MS |
2232 | && TYPE_FIELDS (t) != NULL_TREE); |
2233 | } | |
0171aeab JM |
2234 | else |
2235 | continue; | |
f376e137 | 2236 | |
8dff1027 | 2237 | init = build (COMPONENT_REF, TREE_TYPE (field), init, field); |
f376e137 MS |
2238 | init = build_tree_list (NULL_TREE, init); |
2239 | ||
2240 | current_member_init_list | |
a5894242 | 2241 | = tree_cons (DECL_NAME (field), init, current_member_init_list); |
f376e137 MS |
2242 | } |
2243 | current_member_init_list = nreverse (current_member_init_list); | |
faae18ab | 2244 | current_base_init_list = nreverse (current_base_init_list); |
f376e137 MS |
2245 | setup_vtbl_ptr (); |
2246 | } | |
2247 | ||
2248 | pop_momentary (); | |
f376e137 MS |
2249 | } |
2250 | ||
824b9a4c | 2251 | static void |
db5ae43f | 2252 | do_build_assign_ref (fndecl) |
f376e137 MS |
2253 | tree fndecl; |
2254 | { | |
2255 | tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); | |
2256 | ||
db5ae43f | 2257 | clear_last_expr (); |
f376e137 MS |
2258 | push_momentary (); |
2259 | ||
2260 | parm = convert_from_reference (parm); | |
2261 | ||
a59ca936 JM |
2262 | if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) |
2263 | && is_empty_class (current_class_type)) | |
2264 | /* Don't copy the padding byte; it might not have been allocated | |
2265 | if *this is a base subobject. */; | |
2266 | else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) | |
f376e137 | 2267 | { |
4ac14744 | 2268 | tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); |
f376e137 MS |
2269 | TREE_SIDE_EFFECTS (t) = 1; |
2270 | cplus_expand_expr_stmt (t); | |
2271 | } | |
2272 | else | |
2273 | { | |
2274 | tree fields = TYPE_FIELDS (current_class_type); | |
2275 | int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); | |
2276 | tree binfos = TYPE_BINFO_BASETYPES (current_class_type); | |
2277 | int i; | |
2278 | ||
2279 | for (i = 0; i < n_bases; ++i) | |
2280 | { | |
2281 | tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); | |
e349ee73 MS |
2282 | tree p = convert_to_reference |
2283 | (build_reference_type (basetype), parm, | |
2284 | CONV_IMPLICIT|CONV_CONST, LOOKUP_COMPLAIN, NULL_TREE); | |
2285 | p = convert_from_reference (p); | |
2286 | p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], | |
e66d884e | 2287 | build_expr_list (NULL_TREE, p)); |
e349ee73 | 2288 | expand_expr_stmt (p); |
f376e137 MS |
2289 | } |
2290 | for (; fields; fields = TREE_CHAIN (fields)) | |
2291 | { | |
0171aeab | 2292 | tree comp, init, t; |
a5894242 MS |
2293 | tree field = fields; |
2294 | ||
2295 | if (TREE_CODE (field) != FIELD_DECL) | |
f376e137 | 2296 | continue; |
e349ee73 MS |
2297 | |
2298 | if (TREE_READONLY (field)) | |
2299 | { | |
2300 | if (DECL_NAME (field)) | |
2301 | cp_error ("non-static const member `%#D', can't use default assignment operator", field); | |
2302 | else | |
2303 | cp_error ("non-static const member in type `%T', can't use default assignment operator", current_class_type); | |
2304 | continue; | |
2305 | } | |
2306 | else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) | |
2307 | { | |
2308 | if (DECL_NAME (field)) | |
2309 | cp_error ("non-static reference member `%#D', can't use default assignment operator", field); | |
2310 | else | |
2311 | cp_error ("non-static reference member in type `%T', can't use default assignment operator", current_class_type); | |
2312 | continue; | |
2313 | } | |
2314 | ||
8dff1027 MS |
2315 | comp = current_class_ref; |
2316 | init = parm; | |
2317 | ||
a5894242 | 2318 | if (DECL_NAME (field)) |
f376e137 | 2319 | { |
a5894242 | 2320 | if (VFIELD_NAME_P (DECL_NAME (field))) |
f376e137 | 2321 | continue; |
a5894242 | 2322 | if (VBASE_NAME_P (DECL_NAME (field))) |
f376e137 MS |
2323 | continue; |
2324 | ||
2325 | /* True for duplicate members. */ | |
a5894242 | 2326 | if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) |
f376e137 MS |
2327 | continue; |
2328 | } | |
a5894242 | 2329 | else if ((t = TREE_TYPE (field)) != NULL_TREE |
67ffc812 | 2330 | && ANON_UNION_TYPE_P (t) |
0171aeab | 2331 | && TYPE_FIELDS (t) != NULL_TREE) |
8dff1027 MS |
2332 | { |
2333 | do | |
2334 | { | |
2335 | comp = build (COMPONENT_REF, t, comp, field); | |
2336 | init = build (COMPONENT_REF, t, init, field); | |
2337 | field = largest_union_member (t); | |
2338 | } | |
2339 | while ((t = TREE_TYPE (field)) != NULL_TREE | |
67ffc812 | 2340 | && ANON_UNION_TYPE_P (t) |
8dff1027 MS |
2341 | && TYPE_FIELDS (t) != NULL_TREE); |
2342 | } | |
0171aeab JM |
2343 | else |
2344 | continue; | |
f376e137 | 2345 | |
8dff1027 MS |
2346 | comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); |
2347 | init = build (COMPONENT_REF, TREE_TYPE (field), init, field); | |
f376e137 MS |
2348 | |
2349 | expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); | |
2350 | } | |
2351 | } | |
4ac14744 | 2352 | c_expand_return (current_class_ref); |
f376e137 | 2353 | pop_momentary (); |
f376e137 MS |
2354 | } |
2355 | ||
2356 | void | |
db5ae43f | 2357 | synthesize_method (fndecl) |
f376e137 MS |
2358 | tree fndecl; |
2359 | { | |
db5ae43f | 2360 | int nested = (current_function_decl != NULL_TREE); |
e76a2646 | 2361 | tree context = hack_decl_function_context (fndecl); |
db5ae43f | 2362 | |
b7067a12 JM |
2363 | if (at_eof) |
2364 | import_export_decl (fndecl); | |
2365 | ||
9a3b49ac MS |
2366 | if (! context) |
2367 | push_to_top_level (); | |
2368 | else if (nested) | |
28cbf42c | 2369 | push_cp_function_context (context); |
db5ae43f | 2370 | |
e76a2646 | 2371 | interface_unknown = 1; |
c11b6f21 | 2372 | start_function (NULL_TREE, fndecl, NULL_TREE, 1); |
f376e137 | 2373 | store_parm_decls (); |
db5ae43f MS |
2374 | |
2375 | if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) | |
2376 | do_build_assign_ref (fndecl); | |
2377 | else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) | |
2378 | ; | |
2379 | else | |
2380 | { | |
2381 | tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); | |
2382 | if (DECL_CONSTRUCTOR_FOR_VBASE_P (fndecl)) | |
2383 | arg_chain = TREE_CHAIN (arg_chain); | |
2384 | if (arg_chain != void_list_node) | |
2385 | do_build_copy_constructor (fndecl); | |
2386 | else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) | |
2387 | setup_vtbl_ptr (); | |
2388 | } | |
2389 | ||
2390 | finish_function (lineno, 0, nested); | |
28cbf42c | 2391 | |
db5ae43f | 2392 | extract_interface_info (); |
9a3b49ac MS |
2393 | if (! context) |
2394 | pop_from_top_level (); | |
2395 | else if (nested) | |
28cbf42c | 2396 | pop_cp_function_context (context); |
f376e137 | 2397 | } |