Annotation of gcc/cp/sig.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.