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