1 | /* Functions dealing with signatures and signature pointers/references. |
---|
2 | Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
---|
3 | Contributed by Gerald Baumgartner (gb@cs.purdue.edu) |
---|
4 | |
---|
5 | This file is part of GNU CC. |
---|
6 | |
---|
7 | GNU CC is free software; you can redistribute it and/or modify |
---|
8 | it under the terms of the GNU General Public License as published by |
---|
9 | the Free Software Foundation; either version 2, or (at your option) |
---|
10 | any later version. |
---|
11 | |
---|
12 | GNU CC is distributed in the hope that it will be useful, |
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | GNU General Public License for more details. |
---|
16 | |
---|
17 | You should have received a copy of the GNU General Public License |
---|
18 | along with GNU CC; see the file COPYING. If not, write to |
---|
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
---|
20 | Boston, MA 02111-1307, USA. */ |
---|
21 | |
---|
22 | |
---|
23 | #include "config.h" |
---|
24 | #include <stdio.h> |
---|
25 | #include "obstack.h" |
---|
26 | #include "tree.h" |
---|
27 | #include "cp-tree.h" |
---|
28 | #include "flags.h" |
---|
29 | #include "assert.h" |
---|
30 | |
---|
31 | extern struct obstack *current_obstack; |
---|
32 | extern struct obstack permanent_obstack; |
---|
33 | extern struct obstack *saveable_obstack; |
---|
34 | |
---|
35 | extern void error (); |
---|
36 | extern void sorry (); |
---|
37 | extern void compiler_error (); |
---|
38 | extern void make_decl_rtl PROTO((tree, char *, int)); |
---|
39 | |
---|
40 | /* Used to help generate globally unique names for signature tables. */ |
---|
41 | |
---|
42 | static int global_sigtable_name_counter; |
---|
43 | |
---|
44 | /* Build an identifier for a signature pointer or reference, so we |
---|
45 | can use it's name in function name mangling. */ |
---|
46 | |
---|
47 | static tree |
---|
48 | build_signature_pointer_or_reference_name (to_type, constp, volatilep, refp) |
---|
49 | tree to_type; |
---|
50 | int constp, volatilep, refp; |
---|
51 | { |
---|
52 | char * sig_name = TYPE_NAME_STRING (to_type); |
---|
53 | int name_len = TYPE_NAME_LENGTH (to_type) + constp + volatilep; |
---|
54 | char * name; |
---|
55 | |
---|
56 | if (refp) |
---|
57 | { |
---|
58 | name = (char *) alloca (name_len + sizeof (SIGNATURE_REFERENCE_NAME) +2); |
---|
59 | sprintf (name, SIGNATURE_REFERENCE_NAME_FORMAT, |
---|
60 | constp ? "C" : "", volatilep ? "V": "", sig_name); |
---|
61 | } |
---|
62 | else |
---|
63 | { |
---|
64 | name = (char *) alloca (name_len + sizeof (SIGNATURE_POINTER_NAME) + 2); |
---|
65 | sprintf (name, SIGNATURE_POINTER_NAME_FORMAT, |
---|
66 | constp ? "C" : "", volatilep ? "V": "", sig_name); |
---|
67 | } |
---|
68 | return get_identifier (name); |
---|
69 | } |
---|
70 | |
---|
71 | /* Build a DECL node for a signature pointer or reference, so we can |
---|
72 | tell the debugger the structure of signature pointers/references. |
---|
73 | This function is called at most eight times for a given signature, |
---|
74 | once for each [const] [volatile] signature pointer/reference. */ |
---|
75 | |
---|
76 | static void |
---|
77 | build_signature_pointer_or_reference_decl (type, name) |
---|
78 | tree type, name; |
---|
79 | { |
---|
80 | tree decl; |
---|
81 | |
---|
82 | /* We don't enter this declaration in any sort of symbol table. */ |
---|
83 | decl = build_decl (TYPE_DECL, name, type); |
---|
84 | TYPE_NAME (type) = decl; |
---|
85 | TREE_CHAIN (type) = decl; |
---|
86 | } |
---|
87 | |
---|
88 | /* Construct, lay out and return the type of pointers or references |
---|
89 | to signature TO_TYPE. If such a type has already been constructed, |
---|
90 | reuse it. If CONSTP or VOLATILEP is specified, make the `optr' const |
---|
91 | or volatile, respectively. If we are constructing a const/volatile |
---|
92 | type variant and the main type variant doesn't exist yet, it is built |
---|
93 | as well. If REFP is 1, we construct a signature reference, otherwise |
---|
94 | a signature pointer is constructed. |
---|
95 | |
---|
96 | This function is a subroutine of `build_signature_pointer_type' and |
---|
97 | `build_signature_reference_type'. */ |
---|
98 | |
---|
99 | static tree |
---|
100 | build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp) |
---|
101 | tree to_type; |
---|
102 | int constp, volatilep, refp; |
---|
103 | { |
---|
104 | register tree t, m; |
---|
105 | register struct obstack *ambient_obstack = current_obstack; |
---|
106 | register struct obstack *ambient_saveable_obstack = saveable_obstack; |
---|
107 | |
---|
108 | m = refp ? SIGNATURE_REFERENCE_TO (to_type) : SIGNATURE_POINTER_TO (to_type); |
---|
109 | |
---|
110 | /* If we don't have the main variant yet, construct it. */ |
---|
111 | if (m == NULL_TREE |
---|
112 | && (constp || volatilep)) |
---|
113 | m = build_signature_pointer_or_reference_type (to_type, 0, 0, refp); |
---|
114 | |
---|
115 | /* Treat any nonzero argument as 1. */ |
---|
116 | constp = !!constp; |
---|
117 | volatilep = !!volatilep; |
---|
118 | refp = !!refp; |
---|
119 | |
---|
120 | /* If not generating auxiliary info, search the chain of variants to see |
---|
121 | if there is already one there just like the one we need to have. If so, |
---|
122 | use that existing one. |
---|
123 | |
---|
124 | We don't do this in the case where we are generating aux info because |
---|
125 | in that case we want each typedef names to get it's own distinct type |
---|
126 | node, even if the type of this new typedef is the same as some other |
---|
127 | (existing) type. */ |
---|
128 | |
---|
129 | if (m && !flag_gen_aux_info) |
---|
130 | for (t = m; t; t = TYPE_NEXT_VARIANT (t)) |
---|
131 | if (constp == TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t)))) |
---|
132 | && volatilep == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t))))) |
---|
133 | return t; |
---|
134 | |
---|
135 | /* We need a new one. If TO_TYPE is permanent, make this permanent too. */ |
---|
136 | if (TREE_PERMANENT (to_type)) |
---|
137 | { |
---|
138 | current_obstack = &permanent_obstack; |
---|
139 | saveable_obstack = &permanent_obstack; |
---|
140 | } |
---|
141 | |
---|
142 | /* A signature pointer or reference to a signature `s' looks like this: |
---|
143 | |
---|
144 | struct { |
---|
145 | void * optr; |
---|
146 | const s * sptr; |
---|
147 | }; |
---|
148 | |
---|
149 | A `const' signature pointer/reference is a |
---|
150 | |
---|
151 | struct { |
---|
152 | const void * optr; |
---|
153 | const s * sptr; |
---|
154 | }; |
---|
155 | |
---|
156 | Similarly, for `volatile' and `const volatile'. |
---|
157 | */ |
---|
158 | |
---|
159 | t = make_lang_type (RECORD_TYPE); |
---|
160 | { |
---|
161 | tree obj_type = build_type_variant (void_type_node, constp, volatilep); |
---|
162 | tree optr_type = build_pointer_type (obj_type); |
---|
163 | tree optr, sptr; |
---|
164 | |
---|
165 | optr = build_lang_field_decl (FIELD_DECL, |
---|
166 | get_identifier (SIGNATURE_OPTR_NAME), |
---|
167 | optr_type); |
---|
168 | DECL_FIELD_CONTEXT (optr) = t; |
---|
169 | DECL_CLASS_CONTEXT (optr) = t; |
---|
170 | |
---|
171 | if (m) |
---|
172 | /* We can share the `sptr' field among type variants. */ |
---|
173 | sptr = TREE_CHAIN (TYPE_FIELDS (m)); |
---|
174 | else |
---|
175 | { |
---|
176 | tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0); |
---|
177 | |
---|
178 | sptr = build_lang_field_decl (FIELD_DECL, |
---|
179 | get_identifier (SIGNATURE_SPTR_NAME), |
---|
180 | build_pointer_type (sig_tbl_type)); |
---|
181 | DECL_FIELD_CONTEXT (sptr) = t; |
---|
182 | DECL_CLASS_CONTEXT (sptr) = t; |
---|
183 | TREE_CHAIN (sptr) = NULL_TREE; |
---|
184 | } |
---|
185 | |
---|
186 | TREE_CHAIN (optr) = sptr; |
---|
187 | TYPE_FIELDS (t) = optr; |
---|
188 | TYPE_ALIGN (t) = TYPE_ALIGN (optr_type); |
---|
189 | |
---|
190 | /* A signature pointer/reference type isn't a `real' class type. */ |
---|
191 | IS_AGGR_TYPE (t) = 0; |
---|
192 | } |
---|
193 | |
---|
194 | { |
---|
195 | tree name = build_signature_pointer_or_reference_name (to_type, constp, |
---|
196 | volatilep, refp); |
---|
197 | |
---|
198 | /* Build a DECL node for this type, so the debugger has access to it. */ |
---|
199 | build_signature_pointer_or_reference_decl (t, name); |
---|
200 | } |
---|
201 | |
---|
202 | CLASSTYPE_GOT_SEMICOLON (t) = 1; |
---|
203 | IS_SIGNATURE_POINTER (t) = ! refp; |
---|
204 | IS_SIGNATURE_REFERENCE (t) = refp; |
---|
205 | SIGNATURE_TYPE (t) = to_type; |
---|
206 | |
---|
207 | if (m) |
---|
208 | { |
---|
209 | /* Add this type to the chain of variants of TYPE. |
---|
210 | Every type has to be its own TYPE_MAIN_VARIANT. */ |
---|
211 | TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m); |
---|
212 | TYPE_NEXT_VARIANT (m) = t; |
---|
213 | } |
---|
214 | else if (refp) |
---|
215 | /* Record this type as the reference to TO_TYPE. */ |
---|
216 | SIGNATURE_REFERENCE_TO (to_type) = t; |
---|
217 | else |
---|
218 | /* Record this type as the pointer to TO_TYPE. */ |
---|
219 | SIGNATURE_POINTER_TO (to_type) = t; |
---|
220 | |
---|
221 | /* Lay out the type. This function has many callers that are concerned |
---|
222 | with expression-construction, and this simplifies them all. |
---|
223 | Also, it guarantees the TYPE_SIZE is permanent if the type is. */ |
---|
224 | layout_type (t); |
---|
225 | |
---|
226 | current_obstack = ambient_obstack; |
---|
227 | saveable_obstack = ambient_saveable_obstack; |
---|
228 | |
---|
229 | /* Output debug information for this type. */ |
---|
230 | rest_of_type_compilation (t, 1); |
---|
231 | |
---|
232 | return t; |
---|
233 | } |
---|
234 | |
---|
235 | /* Construct, lay out and return the type of pointers to signature TO_TYPE. */ |
---|
236 | |
---|
237 | tree |
---|
238 | build_signature_pointer_type (to_type, constp, volatilep) |
---|
239 | tree to_type; |
---|
240 | int constp, volatilep; |
---|
241 | { |
---|
242 | return |
---|
243 | build_signature_pointer_or_reference_type (to_type, constp, volatilep, 0); |
---|
244 | } |
---|
245 | |
---|
246 | /* Construct, lay out and return the type of pointers to signature TO_TYPE. */ |
---|
247 | |
---|
248 | tree |
---|
249 | build_signature_reference_type (to_type, constp, volatilep) |
---|
250 | tree to_type; |
---|
251 | int constp, volatilep; |
---|
252 | { |
---|
253 | return |
---|
254 | build_signature_pointer_or_reference_type (to_type, constp, volatilep, 1); |
---|
255 | } |
---|
256 | |
---|
257 | /* Return the name of the signature table (as an IDENTIFIER_NODE) |
---|
258 | for the given signature type SIG_TYPE and rhs type RHS_TYPE. */ |
---|
259 | |
---|
260 | static tree |
---|
261 | get_sigtable_name (sig_type, rhs_type) |
---|
262 | tree sig_type, rhs_type; |
---|
263 | { |
---|
264 | tree sig_type_id = build_typename_overload (sig_type); |
---|
265 | tree rhs_type_id = build_typename_overload (rhs_type); |
---|
266 | char *buf = (char *) alloca (sizeof (SIGTABLE_NAME_FORMAT_LONG) |
---|
267 | + IDENTIFIER_LENGTH (sig_type_id) |
---|
268 | + IDENTIFIER_LENGTH (rhs_type_id) + 20); |
---|
269 | char *sig_ptr = IDENTIFIER_POINTER (sig_type_id); |
---|
270 | char *rhs_ptr = IDENTIFIER_POINTER (rhs_type_id); |
---|
271 | int i, j; |
---|
272 | |
---|
273 | for (i = 0; sig_ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) |
---|
274 | /* do nothing */; |
---|
275 | while (sig_ptr[i] >= '0' && sig_ptr[i] <= '9') |
---|
276 | i += 1; |
---|
277 | |
---|
278 | for (j = 0; rhs_ptr[j] == OPERATOR_TYPENAME_FORMAT[j]; j++) |
---|
279 | /* do nothing */; |
---|
280 | while (rhs_ptr[j] >= '0' && rhs_ptr[j] <= '9') |
---|
281 | j += 1; |
---|
282 | |
---|
283 | if (IS_SIGNATURE (rhs_type)) |
---|
284 | sprintf (buf, SIGTABLE_NAME_FORMAT_LONG, sig_ptr+i, rhs_ptr+j, |
---|
285 | global_sigtable_name_counter++); |
---|
286 | else |
---|
287 | sprintf (buf, SIGTABLE_NAME_FORMAT, sig_ptr+i, rhs_ptr+j); |
---|
288 | return get_identifier (buf); |
---|
289 | } |
---|
290 | |
---|
291 | /* Build a field decl that points to a signature member function. */ |
---|
292 | |
---|
293 | static tree |
---|
294 | build_member_function_pointer (member) |
---|
295 | tree member; |
---|
296 | { |
---|
297 | char *namstr = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (member)); |
---|
298 | int namlen = IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (member)); |
---|
299 | char *name; |
---|
300 | tree entry; |
---|
301 | |
---|
302 | name = (char *) alloca (namlen + sizeof (SIGNATURE_FIELD_NAME) + 2); |
---|
303 | sprintf (name, SIGNATURE_FIELD_NAME_FORMAT, namstr); |
---|
304 | |
---|
305 | /* @@ Do we really want to xref signature table fields? */ |
---|
306 | GNU_xref_ref (current_function_decl, name); |
---|
307 | |
---|
308 | entry = build_lang_field_decl (FIELD_DECL, get_identifier (name), |
---|
309 | TYPE_MAIN_VARIANT (sigtable_entry_type)); |
---|
310 | TREE_CONSTANT (entry) = 1; |
---|
311 | TREE_READONLY (entry) = 1; |
---|
312 | |
---|
313 | /* @@ Do we really want to xref signature table fields? */ |
---|
314 | GNU_xref_decl (current_function_decl, entry); |
---|
315 | |
---|
316 | return entry; |
---|
317 | } |
---|
318 | |
---|
319 | /* For each FUNCTION_DECL in a signature we construct a member function |
---|
320 | pointer of the appropriate type. We also need two flags to test |
---|
321 | whether the member function pointer points to a virtual function or |
---|
322 | to a default implementation. Those flags will be the two lower order |
---|
323 | bits of the member function pointer (or the two higher order bits, |
---|
324 | based on the configuration). |
---|
325 | |
---|
326 | The new FIELD_DECLs are appended at the end of the last (and only) |
---|
327 | sublist of `list_of_fieldlists.' |
---|
328 | |
---|
329 | As a side effect, each member function in the signature gets the |
---|
330 | `decl.ignored' bit turned on, so we don't output debug info for it. */ |
---|
331 | |
---|
332 | void |
---|
333 | append_signature_fields (list_of_fieldlists) |
---|
334 | tree list_of_fieldlists; |
---|
335 | { |
---|
336 | tree l, x; |
---|
337 | tree last_x = NULL_TREE; |
---|
338 | tree mfptr; |
---|
339 | tree last_mfptr; |
---|
340 | tree mfptr_list = NULL_TREE; |
---|
341 | |
---|
342 | /* For signatures it should actually be only a list with one element. */ |
---|
343 | for (l = list_of_fieldlists; l; l = TREE_CHAIN (l)) |
---|
344 | { |
---|
345 | for (x = TREE_VALUE (l); x; x = TREE_CHAIN (x)) |
---|
346 | { |
---|
347 | if (TREE_CODE (x) == FUNCTION_DECL) |
---|
348 | { |
---|
349 | mfptr = build_member_function_pointer (x); |
---|
350 | DECL_MEMFUNC_POINTER_TO (x) = mfptr; |
---|
351 | DECL_MEMFUNC_POINTING_TO (mfptr) = x; |
---|
352 | DECL_IGNORED_P (x) = 1; |
---|
353 | DECL_IN_AGGR_P (mfptr) = 1; |
---|
354 | if (! mfptr_list) |
---|
355 | mfptr_list = last_mfptr = mfptr; |
---|
356 | else |
---|
357 | { |
---|
358 | TREE_CHAIN (last_mfptr) = mfptr; |
---|
359 | last_mfptr = mfptr; |
---|
360 | } |
---|
361 | } |
---|
362 | last_x = x; |
---|
363 | } |
---|
364 | } |
---|
365 | |
---|
366 | /* Append the lists. */ |
---|
367 | if (last_x && mfptr_list) |
---|
368 | { |
---|
369 | TREE_CHAIN (last_x) = mfptr_list; |
---|
370 | TREE_CHAIN (last_mfptr) = NULL_TREE; |
---|
371 | } |
---|
372 | } |
---|
373 | |
---|
374 | /* Compare the types of a signature member function and a class member |
---|
375 | function. Returns 1 if the types are in the C++ `<=' relationship. |
---|
376 | |
---|
377 | If we have a signature pointer/reference as argument or return type |
---|
378 | we don't want to do a recursive conformance check. The conformance |
---|
379 | check only succeeds if both LHS and RHS refer to the same signature |
---|
380 | pointer. Otherwise we need to keep information about parameter types |
---|
381 | around at run time to initialize the signature table correctly. */ |
---|
382 | |
---|
383 | static int |
---|
384 | match_method_types (sig_mtype, class_mtype) |
---|
385 | tree sig_mtype, class_mtype; |
---|
386 | { |
---|
387 | tree sig_return_type = TREE_TYPE (sig_mtype); |
---|
388 | tree sig_arg_types = TYPE_ARG_TYPES (sig_mtype); |
---|
389 | tree class_return_type = TREE_TYPE (class_mtype); |
---|
390 | tree class_arg_types = TYPE_ARG_TYPES (class_mtype); |
---|
391 | |
---|
392 | /* The return types have to be the same. */ |
---|
393 | if (! comptypes (sig_return_type, class_return_type, 1)) |
---|
394 | return 0; |
---|
395 | |
---|
396 | /* Compare the first argument `this.' */ |
---|
397 | { |
---|
398 | /* Get the type of what the `optr' is pointing to. */ |
---|
399 | tree sig_this = |
---|
400 | TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types)))); |
---|
401 | tree class_this = TREE_VALUE (class_arg_types); |
---|
402 | |
---|
403 | if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */ |
---|
404 | class_this = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (class_this))); |
---|
405 | else |
---|
406 | class_this = TREE_TYPE (class_this); |
---|
407 | |
---|
408 | /* If a signature method's `this' is const or volatile, so has to be |
---|
409 | the corresponding class method's `this.' */ |
---|
410 | if ((TYPE_READONLY (sig_this) && ! TYPE_READONLY (class_this)) |
---|
411 | || (TYPE_VOLATILE (sig_this) && ! TYPE_VOLATILE (class_this))) |
---|
412 | return 0; |
---|
413 | } |
---|
414 | |
---|
415 | sig_arg_types = TREE_CHAIN (sig_arg_types); |
---|
416 | class_arg_types = TREE_CHAIN (class_arg_types); |
---|
417 | |
---|
418 | /* The number of arguments and the argument types have to be the same. */ |
---|
419 | return compparms (sig_arg_types, class_arg_types, 3); |
---|
420 | } |
---|
421 | |
---|
422 | /* Undo casts of opaque type variables to the RHS types. */ |
---|
423 | static void |
---|
424 | undo_casts (sig_ty) |
---|
425 | tree sig_ty; |
---|
426 | { |
---|
427 | tree field = TYPE_FIELDS (sig_ty); |
---|
428 | |
---|
429 | /* Since all the FIELD_DECLs for the signature table entries are at the end |
---|
430 | of the chain (see `append_signature_fields'), we can do it this way. */ |
---|
431 | for (; field && TREE_CODE (field) != FIELD_DECL; field = TREE_CHAIN (field)) |
---|
432 | if (TYPE_MAIN_VARIANT (TREE_TYPE (field)) == opaque_type_node) |
---|
433 | TREE_TYPE (TREE_TYPE (field)) = TREE_TYPE (ptr_type_node); |
---|
434 | } |
---|
435 | |
---|
436 | /* Do the type checking necessary to see whether the `rhs' conforms to |
---|
437 | the lhs's `sig_ty'. Depending on the type of `rhs' return a NULL_TREE, |
---|
438 | an integer_zero_node, a constructor, or an expression offsetting the |
---|
439 | `rhs' signature table. */ |
---|
440 | |
---|
441 | static tree |
---|
442 | build_signature_table_constructor (sig_ty, rhs) |
---|
443 | tree sig_ty, rhs; |
---|
444 | { |
---|
445 | tree rhstype = TREE_TYPE (rhs); |
---|
446 | tree sig_field = TYPE_FIELDS (sig_ty); |
---|
447 | tree result = NULL_TREE; |
---|
448 | tree first_rhs_field = NULL_TREE; |
---|
449 | tree last_rhs_field; |
---|
450 | int sig_ptr_p = IS_SIGNATURE (rhstype); |
---|
451 | int offset_p = sig_ptr_p; |
---|
452 | |
---|
453 | rhstype = sig_ptr_p ? rhstype : TREE_TYPE (rhstype); |
---|
454 | |
---|
455 | if (CLASSTYPE_TAGS (sig_ty)) |
---|
456 | { |
---|
457 | sorry ("conformance check with signature containing class declarations"); |
---|
458 | return error_mark_node; |
---|
459 | } |
---|
460 | |
---|
461 | for (; sig_field; sig_field = TREE_CHAIN (sig_field)) |
---|
462 | { |
---|
463 | tree basetype_path, baselink, basetypes; |
---|
464 | tree sig_method, sig_mname, sig_mtype; |
---|
465 | tree rhs_method, tbl_entry; |
---|
466 | |
---|
467 | if (TREE_CODE (sig_field) == TYPE_DECL) |
---|
468 | { |
---|
469 | tree sig_field_type = TREE_TYPE (sig_field); |
---|
470 | |
---|
471 | if (TYPE_MAIN_VARIANT (sig_field_type) == opaque_type_node) |
---|
472 | { |
---|
473 | /* We've got an opaque type here. */ |
---|
474 | tree oty_name = DECL_NAME (sig_field); |
---|
475 | tree oty_type = lookup_field (rhstype, oty_name, 1, 1); |
---|
476 | |
---|
477 | if (oty_type == NULL_TREE || oty_type == error_mark_node) |
---|
478 | { |
---|
479 | cp_error ("class `%T' does not contain type `%T'", |
---|
480 | rhstype, oty_type); |
---|
481 | undo_casts (sig_ty); |
---|
482 | return error_mark_node; |
---|
483 | } |
---|
484 | oty_type = TREE_TYPE (oty_type); |
---|
485 | |
---|
486 | /* Cast `sig_field' to be of type `oty_type'. This will be |
---|
487 | undone in `undo_casts' by walking over all the TYPE_DECLs. */ |
---|
488 | TREE_TYPE (sig_field_type) = TREE_TYPE (oty_type); |
---|
489 | } |
---|
490 | /* If we don't have an opaque type, we can ignore the `typedef'. */ |
---|
491 | continue; |
---|
492 | } |
---|
493 | |
---|
494 | /* Find the signature method corresponding to `sig_field'. */ |
---|
495 | sig_method = DECL_MEMFUNC_POINTING_TO (sig_field); |
---|
496 | sig_mname = DECL_NAME (sig_method); |
---|
497 | sig_mtype = TREE_TYPE (sig_method); |
---|
498 | |
---|
499 | basetype_path = TYPE_BINFO (rhstype); |
---|
500 | baselink = lookup_fnfields (basetype_path, sig_mname, 0); |
---|
501 | if (baselink == NULL_TREE || baselink == error_mark_node) |
---|
502 | { |
---|
503 | if (! IS_DEFAULT_IMPLEMENTATION (sig_method)) |
---|
504 | { |
---|
505 | cp_error ("class `%T' does not contain method `%D'", |
---|
506 | rhstype, sig_mname); |
---|
507 | undo_casts (sig_ty); |
---|
508 | return error_mark_node; |
---|
509 | } |
---|
510 | else |
---|
511 | { |
---|
512 | /* We use the signature's default implementation. */ |
---|
513 | rhs_method = sig_method; |
---|
514 | } |
---|
515 | } |
---|
516 | else |
---|
517 | { |
---|
518 | /* Find the class method of the correct type. */ |
---|
519 | |
---|
520 | basetypes = TREE_PURPOSE (baselink); |
---|
521 | if (TREE_CODE (basetypes) == TREE_LIST) |
---|
522 | basetypes = TREE_VALUE (basetypes); |
---|
523 | |
---|
524 | rhs_method = TREE_VALUE (baselink); |
---|
525 | for (; rhs_method; rhs_method = TREE_CHAIN (rhs_method)) |
---|
526 | if (sig_mname == DECL_NAME (rhs_method) |
---|
527 | && ! DECL_STATIC_FUNCTION_P (rhs_method) |
---|
528 | && match_method_types (sig_mtype, TREE_TYPE (rhs_method))) |
---|
529 | break; |
---|
530 | |
---|
531 | if (rhs_method == NULL_TREE |
---|
532 | || (compute_access (basetypes, rhs_method) |
---|
533 | != access_public)) |
---|
534 | { |
---|
535 | error ("class `%s' does not contain a method conforming to `%s'", |
---|
536 | TYPE_NAME_STRING (rhstype), |
---|
537 | fndecl_as_string (NULL, sig_method, 1)); |
---|
538 | undo_casts (sig_ty); |
---|
539 | return error_mark_node; |
---|
540 | } |
---|
541 | } |
---|
542 | |
---|
543 | if (sig_ptr_p && rhs_method != sig_method) |
---|
544 | { |
---|
545 | tree rhs_field = DECL_MEMFUNC_POINTER_TO (rhs_method); |
---|
546 | |
---|
547 | if (first_rhs_field == NULL_TREE) |
---|
548 | { |
---|
549 | first_rhs_field = rhs_field; |
---|
550 | last_rhs_field = rhs_field; |
---|
551 | } |
---|
552 | else if (TREE_CHAIN (last_rhs_field) == rhs_field) |
---|
553 | last_rhs_field = rhs_field; |
---|
554 | else |
---|
555 | offset_p = 0; |
---|
556 | |
---|
557 | tbl_entry = build_component_ref (rhs, DECL_NAME (rhs_field), |
---|
558 | NULL_TREE, 1); |
---|
559 | } |
---|
560 | else |
---|
561 | { |
---|
562 | tree tag, vb_off, delta, index, pfn, vt_off; |
---|
563 | tree tag_decl, vb_off_decl, delta_decl, index_decl; |
---|
564 | tree pfn_decl, vt_off_decl; |
---|
565 | |
---|
566 | if (rhs_method == sig_method) |
---|
567 | { |
---|
568 | /* default implementation */ |
---|
569 | tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0); |
---|
570 | vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); |
---|
571 | delta = integer_zero_node; |
---|
572 | index = integer_zero_node; |
---|
573 | pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); |
---|
574 | TREE_TYPE (pfn) = ptr_type_node; |
---|
575 | TREE_ADDRESSABLE (rhs_method) = 1; |
---|
576 | offset_p = 0; /* we can't offset the rhs sig table */ |
---|
577 | } |
---|
578 | else if (DECL_VINDEX (rhs_method)) |
---|
579 | { |
---|
580 | /* virtual member function */ |
---|
581 | tag = integer_one_node; |
---|
582 | vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); |
---|
583 | delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), |
---|
584 | rhstype, 1)); |
---|
585 | index = DECL_VINDEX (rhs_method); |
---|
586 | vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method), |
---|
587 | rhstype, 0)); |
---|
588 | } |
---|
589 | else |
---|
590 | { |
---|
591 | /* non-virtual member function */ |
---|
592 | tag = integer_zero_node; |
---|
593 | vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0); |
---|
594 | delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method), |
---|
595 | rhstype, 1)); |
---|
596 | index = integer_zero_node; |
---|
597 | pfn = build_unary_op (ADDR_EXPR, rhs_method, 0); |
---|
598 | TREE_TYPE (pfn) = ptr_type_node; |
---|
599 | TREE_ADDRESSABLE (rhs_method) = 1; |
---|
600 | } |
---|
601 | |
---|
602 | /* Since digest_init doesn't handle initializing selected fields |
---|
603 | of a struct (i.e., anonymous union), we build the constructor |
---|
604 | by hand, without calling digest_init. */ |
---|
605 | tag_decl = TYPE_FIELDS (sigtable_entry_type); |
---|
606 | vb_off_decl = TREE_CHAIN (tag_decl); |
---|
607 | delta_decl = TREE_CHAIN (vb_off_decl); |
---|
608 | index_decl = TREE_CHAIN (delta_decl); |
---|
609 | pfn_decl = TREE_CHAIN (index_decl); |
---|
610 | vt_off_decl = TREE_CHAIN (pfn_decl); |
---|
611 | |
---|
612 | tag = convert (TREE_TYPE (tag_decl), tag); |
---|
613 | vb_off = convert (TREE_TYPE (vb_off_decl), vb_off); |
---|
614 | delta = convert (TREE_TYPE (delta_decl), delta); |
---|
615 | index = convert (TREE_TYPE (index_decl), index); |
---|
616 | |
---|
617 | if (DECL_VINDEX (rhs_method)) |
---|
618 | { |
---|
619 | vt_off = convert (TREE_TYPE (vt_off_decl), vt_off); |
---|
620 | |
---|
621 | tbl_entry = build_tree_list (vt_off_decl, vt_off); |
---|
622 | } |
---|
623 | else |
---|
624 | { |
---|
625 | pfn = convert (TREE_TYPE (pfn_decl), pfn); |
---|
626 | |
---|
627 | tbl_entry = build_tree_list (pfn_decl, pfn); |
---|
628 | } |
---|
629 | tbl_entry = tree_cons (delta_decl, delta, |
---|
630 | tree_cons (index_decl, index, tbl_entry)); |
---|
631 | tbl_entry = tree_cons (tag_decl, tag, |
---|
632 | tree_cons (vb_off_decl, vb_off, tbl_entry)); |
---|
633 | tbl_entry = build (CONSTRUCTOR, sigtable_entry_type, |
---|
634 | NULL_TREE, tbl_entry); |
---|
635 | |
---|
636 | TREE_CONSTANT (tbl_entry) = 1; |
---|
637 | } |
---|
638 | |
---|
639 | /* Chain those function address expressions together. */ |
---|
640 | if (result) |
---|
641 | result = tree_cons (NULL_TREE, tbl_entry, result); |
---|
642 | else |
---|
643 | result = build_tree_list (NULL_TREE, tbl_entry); |
---|
644 | } |
---|
645 | |
---|
646 | if (result == NULL_TREE) |
---|
647 | { |
---|
648 | /* The signature was empty, we don't need a signature table. */ |
---|
649 | undo_casts (sig_ty); |
---|
650 | return NULL_TREE; |
---|
651 | } |
---|
652 | |
---|
653 | if (offset_p) |
---|
654 | { |
---|
655 | if (first_rhs_field == TYPE_FIELDS (rhstype)) |
---|
656 | { |
---|
657 | /* The sptr field on the lhs can be copied from the rhs. */ |
---|
658 | undo_casts (sig_ty); |
---|
659 | return integer_zero_node; |
---|
660 | } |
---|
661 | else |
---|
662 | { |
---|
663 | /* The sptr field on the lhs will point into the rhs sigtable. */ |
---|
664 | undo_casts (sig_ty); |
---|
665 | return build_component_ref (rhs, DECL_NAME (first_rhs_field), |
---|
666 | NULL_TREE, 0); |
---|
667 | } |
---|
668 | } |
---|
669 | |
---|
670 | /* We need to construct a new signature table. */ |
---|
671 | result = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (result)); |
---|
672 | TREE_HAS_CONSTRUCTOR (result) = 1; |
---|
673 | TREE_CONSTANT (result) = !sig_ptr_p; |
---|
674 | |
---|
675 | undo_casts (sig_ty); |
---|
676 | return result; |
---|
677 | } |
---|
678 | |
---|
679 | /* Build a signature table declaration and initialize it or return an |
---|
680 | existing one if we built one already. If we don't get a constructor |
---|
681 | as initialization expression, we don't need a new signature table |
---|
682 | variable and just hand back the init expression. |
---|
683 | |
---|
684 | The declaration processing is done by hand instead of using `cp_finish_decl' |
---|
685 | so that we can make signature pointers global variables instead of |
---|
686 | static ones. */ |
---|
687 | |
---|
688 | static tree |
---|
689 | build_sigtable (sig_type, rhs_type, init_from) |
---|
690 | tree sig_type, rhs_type, init_from; |
---|
691 | { |
---|
692 | tree name = NULL_TREE; |
---|
693 | tree decl = NULL_TREE; |
---|
694 | tree init_expr; |
---|
695 | |
---|
696 | push_obstacks_nochange (); |
---|
697 | end_temporary_allocation (); |
---|
698 | |
---|
699 | if (! IS_SIGNATURE (rhs_type)) |
---|
700 | { |
---|
701 | name = get_sigtable_name (sig_type, rhs_type); |
---|
702 | decl = IDENTIFIER_GLOBAL_VALUE (name); |
---|
703 | } |
---|
704 | if (decl == NULL_TREE) |
---|
705 | { |
---|
706 | tree init; |
---|
707 | |
---|
708 | /* We allow only one signature table to be generated for signatures |
---|
709 | with opaque types. Otherwise we create a loophole in the type |
---|
710 | system since we could cast data from one classes implementation |
---|
711 | of the opaque type to that of another class. */ |
---|
712 | if (SIGNATURE_HAS_OPAQUE_TYPEDECLS (sig_type) |
---|
713 | && SIGTABLE_HAS_BEEN_GENERATED (sig_type)) |
---|
714 | { |
---|
715 | error ("signature with opaque type implemented by multiple classes"); |
---|
716 | return error_mark_node; |
---|
717 | } |
---|
718 | SIGTABLE_HAS_BEEN_GENERATED (sig_type) = 1; |
---|
719 | |
---|
720 | init_expr = build_signature_table_constructor (sig_type, init_from); |
---|
721 | if (init_expr == NULL_TREE || TREE_CODE (init_expr) != CONSTRUCTOR) |
---|
722 | return init_expr; |
---|
723 | |
---|
724 | if (name == NULL_TREE) |
---|
725 | name = get_sigtable_name (sig_type, rhs_type); |
---|
726 | { |
---|
727 | tree context = current_function_decl; |
---|
728 | |
---|
729 | /* Make the signature table global, not just static in whichever |
---|
730 | function a signature pointer/ref is used for the first time. */ |
---|
731 | current_function_decl = NULL_TREE; |
---|
732 | decl = pushdecl_top_level (build_decl (VAR_DECL, name, sig_type)); |
---|
733 | current_function_decl = context; |
---|
734 | } |
---|
735 | IDENTIFIER_GLOBAL_VALUE (name) = decl; |
---|
736 | store_init_value (decl, init_expr); |
---|
737 | if (IS_SIGNATURE (rhs_type)) |
---|
738 | { |
---|
739 | init = DECL_INITIAL (decl); |
---|
740 | DECL_INITIAL (decl) = error_mark_node; |
---|
741 | } |
---|
742 | |
---|
743 | DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node), |
---|
744 | DECL_ALIGN (decl)); |
---|
745 | #if 0 |
---|
746 | /* GDB-4.7 doesn't find the initialization value of a signature table |
---|
747 | when it is constant. */ |
---|
748 | TREE_READONLY (decl) = 1; |
---|
749 | #endif |
---|
750 | TREE_STATIC (decl) = 1; |
---|
751 | TREE_USED (decl) = 1; |
---|
752 | |
---|
753 | make_decl_rtl (decl, NULL, 1); |
---|
754 | if (IS_SIGNATURE (rhs_type)) |
---|
755 | expand_static_init (decl, init); |
---|
756 | } |
---|
757 | |
---|
758 | pop_obstacks (); |
---|
759 | |
---|
760 | return decl; |
---|
761 | } |
---|
762 | |
---|
763 | /* Create a constructor or modify expression if the LHS of an assignment |
---|
764 | is a signature pointer or a signature reference. If LHS is a record |
---|
765 | type node, we build a constructor, otherwise a compound expression. */ |
---|
766 | |
---|
767 | tree |
---|
768 | build_signature_pointer_constructor (lhs, rhs) |
---|
769 | tree lhs, rhs; |
---|
770 | { |
---|
771 | register struct obstack *ambient_obstack = current_obstack; |
---|
772 | register struct obstack *ambient_saveable_obstack = saveable_obstack; |
---|
773 | int initp = (TREE_CODE (lhs) == RECORD_TYPE); |
---|
774 | tree lhstype = initp ? lhs : TREE_TYPE (lhs); |
---|
775 | tree rhstype = TREE_TYPE (rhs); |
---|
776 | tree sig_ty = SIGNATURE_TYPE (lhstype); |
---|
777 | tree sig_tbl, sptr_expr, optr_expr; |
---|
778 | tree result; |
---|
779 | |
---|
780 | if (! ((TREE_CODE (rhstype) == POINTER_TYPE |
---|
781 | && TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE) |
---|
782 | || (TYPE_LANG_SPECIFIC (rhstype) && |
---|
783 | (IS_SIGNATURE_POINTER (rhstype) |
---|
784 | || IS_SIGNATURE_REFERENCE (rhstype))))) |
---|
785 | { |
---|
786 | error ("invalid assignment to signature pointer or reference"); |
---|
787 | return error_mark_node; |
---|
788 | } |
---|
789 | |
---|
790 | if (TYPE_SIZE (sig_ty) == NULL_TREE) |
---|
791 | { |
---|
792 | cp_error ("undefined signature `%T' used in signature %s declaration", |
---|
793 | sig_ty, |
---|
794 | IS_SIGNATURE_POINTER (lhstype) ? "pointer" : "reference"); |
---|
795 | return error_mark_node; |
---|
796 | } |
---|
797 | |
---|
798 | /* If SIG_TY is permanent, make the signature table constructor and |
---|
799 | the signature pointer/reference constructor permanent too. */ |
---|
800 | if (TREE_PERMANENT (sig_ty)) |
---|
801 | { |
---|
802 | current_obstack = &permanent_obstack; |
---|
803 | saveable_obstack = &permanent_obstack; |
---|
804 | } |
---|
805 | |
---|
806 | if (TYPE_LANG_SPECIFIC (rhstype) && |
---|
807 | (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype))) |
---|
808 | { |
---|
809 | if (SIGNATURE_TYPE (rhstype) == sig_ty) |
---|
810 | { |
---|
811 | /* LHS and RHS are signature pointers/refs of the same signature. */ |
---|
812 | optr_expr = build_optr_ref (rhs); |
---|
813 | sptr_expr = build_sptr_ref (rhs); |
---|
814 | } |
---|
815 | else |
---|
816 | { |
---|
817 | /* We need to create a new signature table and copy |
---|
818 | elements from the rhs signature table. */ |
---|
819 | tree rhs_sptr_ref = build_sptr_ref (rhs); |
---|
820 | tree rhs_tbl = build1 (INDIRECT_REF, SIGNATURE_TYPE (rhstype), |
---|
821 | rhs_sptr_ref); |
---|
822 | |
---|
823 | sig_tbl = build_sigtable (sig_ty, SIGNATURE_TYPE (rhstype), rhs_tbl); |
---|
824 | if (sig_tbl == error_mark_node) |
---|
825 | return error_mark_node; |
---|
826 | |
---|
827 | optr_expr = build_optr_ref (rhs); |
---|
828 | if (sig_tbl == NULL_TREE) |
---|
829 | /* The signature was empty. The signature pointer is |
---|
830 | pretty useless, but the user has been warned. */ |
---|
831 | sptr_expr = copy_node (null_pointer_node); |
---|
832 | else if (sig_tbl == integer_zero_node) |
---|
833 | sptr_expr = rhs_sptr_ref; |
---|
834 | else |
---|
835 | sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); |
---|
836 | TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); |
---|
837 | } |
---|
838 | } |
---|
839 | else |
---|
840 | { |
---|
841 | sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs); |
---|
842 | if (sig_tbl == error_mark_node) |
---|
843 | return error_mark_node; |
---|
844 | |
---|
845 | optr_expr = rhs; |
---|
846 | if (sig_tbl == NULL_TREE) |
---|
847 | /* The signature was empty. The signature pointer is |
---|
848 | pretty useless, but the user has been warned. */ |
---|
849 | { |
---|
850 | sptr_expr = copy_node (null_pointer_node); |
---|
851 | TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty); |
---|
852 | } |
---|
853 | else |
---|
854 | sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0); |
---|
855 | } |
---|
856 | |
---|
857 | if (initp) |
---|
858 | { |
---|
859 | result = tree_cons (NULL_TREE, optr_expr, |
---|
860 | build_tree_list (NULL_TREE, sptr_expr)); |
---|
861 | result = build_nt (CONSTRUCTOR, NULL_TREE, result); |
---|
862 | TREE_HAS_CONSTRUCTOR (result) = 1; |
---|
863 | result = digest_init (lhstype, result, 0); |
---|
864 | } |
---|
865 | else |
---|
866 | { |
---|
867 | if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)) |
---|
868 | readonly_error (lhs, "assignment", 0); |
---|
869 | |
---|
870 | optr_expr = build_modify_expr (build_optr_ref (lhs), NOP_EXPR, |
---|
871 | optr_expr); |
---|
872 | sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR, |
---|
873 | sptr_expr); |
---|
874 | |
---|
875 | result = tree_cons (NULL_TREE, optr_expr, |
---|
876 | tree_cons (NULL_TREE, sptr_expr, |
---|
877 | build_tree_list (NULL_TREE, lhs))); |
---|
878 | result = build_compound_expr (result); |
---|
879 | } |
---|
880 | |
---|
881 | current_obstack = ambient_obstack; |
---|
882 | saveable_obstack = ambient_saveable_obstack; |
---|
883 | return result; |
---|
884 | } |
---|
885 | |
---|
886 | /* Build a temporary variable declaration for the instance of a signature |
---|
887 | member function call if it isn't a declaration node already. Simply |
---|
888 | using a SAVE_EXPR doesn't work since we need `this' in both branches |
---|
889 | of a conditional expression. */ |
---|
890 | |
---|
891 | static tree |
---|
892 | save_this (instance) |
---|
893 | tree instance; |
---|
894 | { |
---|
895 | tree decl; |
---|
896 | |
---|
897 | if (TREE_CODE_CLASS (TREE_CODE (instance)) == 'd') |
---|
898 | decl = instance; |
---|
899 | else |
---|
900 | { |
---|
901 | decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (instance)); |
---|
902 | DECL_REGISTER (decl) = 1; |
---|
903 | layout_decl (decl, 0); |
---|
904 | expand_decl (decl); |
---|
905 | } |
---|
906 | |
---|
907 | return decl; |
---|
908 | } |
---|
909 | |
---|
910 | /* Build a signature member function call. Looks up the signature table |
---|
911 | entry corresponding to FUNCTION. Depending on the value of the CODE |
---|
912 | field, either call the function in PFN directly, or use OFFSET to |
---|
913 | index INSTANCE's virtual function table. */ |
---|
914 | |
---|
915 | tree |
---|
916 | build_signature_method_call (basetype, instance, function, parms) |
---|
917 | tree basetype, instance, function, parms; |
---|
918 | { |
---|
919 | tree saved_instance = save_this (instance); /* Create temp for `this'. */ |
---|
920 | tree object_ptr = build_optr_ref (saved_instance); |
---|
921 | tree new_object_ptr, new_parms; |
---|
922 | tree signature_tbl_ptr = build_sptr_ref (saved_instance); |
---|
923 | tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function)); |
---|
924 | tree basetype_path = TYPE_BINFO (basetype); |
---|
925 | tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype, |
---|
926 | signature_tbl_ptr), |
---|
927 | sig_field_name, basetype_path, 1); |
---|
928 | tree tag, delta, pfn, vt_off, index, vfn; |
---|
929 | tree deflt_call = NULL_TREE, direct_call, virtual_call, result; |
---|
930 | |
---|
931 | tbl_entry = save_expr (tbl_entry); |
---|
932 | tag = build_component_ref (tbl_entry, tag_identifier, NULL_TREE, 1); |
---|
933 | delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1); |
---|
934 | pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1); |
---|
935 | vt_off = build_component_ref (tbl_entry, vt_off_identifier, NULL_TREE, 1); |
---|
936 | index = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1); |
---|
937 | TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function)); |
---|
938 | |
---|
939 | if (IS_DEFAULT_IMPLEMENTATION (function)) |
---|
940 | { |
---|
941 | pfn = save_expr (pfn); |
---|
942 | deflt_call = build_function_call (pfn, parms); |
---|
943 | } |
---|
944 | |
---|
945 | new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype), |
---|
946 | convert (ptrdiff_type_node, object_ptr), |
---|
947 | convert (ptrdiff_type_node, delta)); |
---|
948 | |
---|
949 | parms = tree_cons (NULL_TREE, |
---|
950 | convert (build_pointer_type (basetype), object_ptr), |
---|
951 | TREE_CHAIN (parms)); |
---|
952 | new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms)); |
---|
953 | |
---|
954 | { |
---|
955 | /* Cast the signature method to have `this' of a normal pointer type. */ |
---|
956 | tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))); |
---|
957 | |
---|
958 | TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = |
---|
959 | build_type_variant (build_pointer_type (basetype), |
---|
960 | TYPE_READONLY (old_this), |
---|
961 | TYPE_VOLATILE (old_this)); |
---|
962 | |
---|
963 | direct_call = build_function_call (pfn, new_parms); |
---|
964 | |
---|
965 | { |
---|
966 | tree vfld, vtbl, aref; |
---|
967 | |
---|
968 | vfld = build (PLUS_EXPR, |
---|
969 | build_pointer_type (build_pointer_type (vtbl_type_node)), |
---|
970 | convert (ptrdiff_type_node, object_ptr), |
---|
971 | convert (ptrdiff_type_node, vt_off)); |
---|
972 | vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR), |
---|
973 | NULL_PTR); |
---|
974 | aref = build_array_ref (vtbl, index); |
---|
975 | |
---|
976 | if (flag_vtable_thunks) |
---|
977 | vfn = aref; |
---|
978 | else |
---|
979 | vfn = build_component_ref (aref, pfn_identifier, 0, 0); |
---|
980 | |
---|
981 | TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function)); |
---|
982 | |
---|
983 | if (flag_vtable_thunks) |
---|
984 | virtual_call = build_function_call (vfn, parms); |
---|
985 | else |
---|
986 | virtual_call = build_function_call (vfn, new_parms); |
---|
987 | } |
---|
988 | |
---|
989 | /* Undo the cast, make `this' a signature pointer again. */ |
---|
990 | TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this; |
---|
991 | } |
---|
992 | |
---|
993 | /* Once the function was found, there should be no reason why we |
---|
994 | couldn't build the member function pointer call. */ |
---|
995 | if (!direct_call || direct_call == error_mark_node |
---|
996 | || !virtual_call || virtual_call == error_mark_node |
---|
997 | || (IS_DEFAULT_IMPLEMENTATION (function) |
---|
998 | && (!deflt_call || deflt_call == error_mark_node))) |
---|
999 | { |
---|
1000 | compiler_error ("cannot build call of signature member function `%s'", |
---|
1001 | fndecl_as_string (NULL, function, 1)); |
---|
1002 | return error_mark_node; |
---|
1003 | } |
---|
1004 | |
---|
1005 | if (IS_DEFAULT_IMPLEMENTATION (function)) |
---|
1006 | { |
---|
1007 | tree test = build_binary_op_nodefault (LT_EXPR, tag, integer_zero_node, |
---|
1008 | LT_EXPR); |
---|
1009 | result = build_conditional_expr (tag, |
---|
1010 | build_conditional_expr (test, |
---|
1011 | deflt_call, |
---|
1012 | virtual_call), |
---|
1013 | direct_call); |
---|
1014 | } |
---|
1015 | else |
---|
1016 | result = build_conditional_expr (tag, virtual_call, direct_call); |
---|
1017 | |
---|
1018 | /* If we created a temporary variable for `this', initialize it first. */ |
---|
1019 | if (instance != saved_instance) |
---|
1020 | result = build (COMPOUND_EXPR, TREE_TYPE (result), |
---|
1021 | build_modify_expr (saved_instance, NOP_EXPR, instance), |
---|
1022 | result); |
---|
1023 | |
---|
1024 | return result; |
---|
1025 | } |
---|
1026 | |
---|
1027 | /* Create a COMPONENT_REF expression for referencing the OPTR field |
---|
1028 | of a signature pointer or reference. */ |
---|
1029 | |
---|
1030 | tree |
---|
1031 | build_optr_ref (instance) |
---|
1032 | tree instance; |
---|
1033 | { |
---|
1034 | tree field = get_identifier (SIGNATURE_OPTR_NAME); |
---|
1035 | |
---|
1036 | return build_component_ref (instance, field, NULL_TREE, 1); |
---|
1037 | } |
---|
1038 | |
---|
1039 | /* Create a COMPONENT_REF expression for referencing the SPTR field |
---|
1040 | of a signature pointer or reference. */ |
---|
1041 | |
---|
1042 | tree |
---|
1043 | build_sptr_ref (instance) |
---|
1044 | tree instance; |
---|
1045 | { |
---|
1046 | tree field = get_identifier (SIGNATURE_SPTR_NAME); |
---|
1047 | |
---|
1048 | return build_component_ref (instance, field, NULL_TREE, 1); |
---|
1049 | } |
---|