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