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

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

unix.superglobalmegacorp.com

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