Annotation of gcc/cp/sig.c, revision 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.