📄 method.c
字号:
/* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#ifndef __GNUC__#define __inline#endif#ifndef PARM_CAN_BE_ARRAY_TYPE#define PARM_CAN_BE_ARRAY_TYPE 1#endif/* Handle method declarations. */#include "config.h"#include "system.h"#include "tree.h"#include "cp-tree.h"#include "obstack.h"#include "rtl.h"#include "expr.h"#include "output.h"#include "hard-reg-set.h"#include "flags.h"#include "toplev.h"#include "decl.h"/* TREE_LIST of the current inline functions that need to be processed. */struct pending_inline *pending_inlines;int static_labelno;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free/* Obstack where we build text strings for overloading, etc. */static struct obstack scratch_obstack;static char *scratch_firstobj;static void icat PROTO((HOST_WIDE_INT));static void dicat PROTO((HOST_WIDE_INT, HOST_WIDE_INT));static int old_backref_index PROTO((tree));static int flush_repeats PROTO((int, tree));static void build_overload_identifier PROTO((tree));static void build_overload_nested_name PROTO((tree));static void build_overload_int PROTO((tree, int));static void build_overload_identifier PROTO((tree));static void build_qualified_name PROTO((tree));static void build_overload_value PROTO((tree, tree, int));static void issue_nrepeats PROTO((int, tree));static char *build_mangled_name PROTO((tree,int,int));static void process_modifiers PROTO((tree));static void process_overload_item PROTO((tree,int));static void do_build_assign_ref PROTO((tree));static void do_build_copy_constructor PROTO((tree));static tree largest_union_member PROTO((tree));static void build_template_template_parm_names PROTO((tree));static void build_template_parm_names PROTO((tree, tree));static void build_underscore_int PROTO((int));static void start_squangling PROTO((void));static void end_squangling PROTO((void));static int check_ktype PROTO((tree, int));static int issue_ktype PROTO((tree));static void build_overload_scope_ref PROTO((tree));static void build_mangled_template_parm_index PROTO((char *, tree));#if HOST_BITS_PER_WIDE_INT >= 64static void build_mangled_C9x_name PROTO((int));#endifstatic int is_back_referenceable_type PROTO((tree));static int check_btype PROTO((tree));static void build_mangled_name_for_type PROTO((tree));static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));static tree build_base_path PROTO((tree, int));# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))# define OB_PUTC2(C1,C2) \ (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))# define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))# define OB_PUTID(ID) \ (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \ IDENTIFIER_LENGTH (ID)))# define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))# define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))# define OB_LAST() (obstack_next_free (&scratch_obstack)[-1])voidinit_method (){ gcc_obstack_init (&scratch_obstack); scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);}/* This must be large enough to hold any printed integer or floating-point value. */static char digit_buffer[128];/* Move inline function definitions out of structure so that they can be processed normally. CNAME is the name of the class we are working from, METHOD_LIST is the list of method lists of the structure. We delete friend methods here, after saving away their inline function definitions (if any). */voiddo_inline_function_hair (type, friend_list) tree type, friend_list;{ tree method = TYPE_METHODS (type); if (method && TREE_CODE (method) == TREE_VEC) { if (TREE_VEC_ELT (method, 1)) method = TREE_VEC_ELT (method, 1); else if (TREE_VEC_ELT (method, 0)) method = TREE_VEC_ELT (method, 0); else method = TREE_VEC_ELT (method, 2); } while (method) { /* Do inline member functions. */ struct pending_inline *info = DECL_PENDING_INLINE_INFO (method); if (info) { tree args; my_friendly_assert (info->fndecl == method, 238); args = DECL_ARGUMENTS (method); while (args) { DECL_CONTEXT (args) = method; args = TREE_CHAIN (args); } } method = TREE_CHAIN (method); } while (friend_list) { tree fndecl = TREE_VALUE (friend_list); struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl); if (info) { tree args; my_friendly_assert (info->fndecl == fndecl, 239); args = DECL_ARGUMENTS (fndecl); while (args) { DECL_CONTEXT (args) = fndecl; args = TREE_CHAIN (args); } } friend_list = TREE_CHAIN (friend_list); }}/* Here is where overload code starts. *//* type tables for K and B type compression */static tree *btypelist = NULL;static tree *ktypelist = NULL;static int maxbsize = 0;static int maxksize = 0;/* number of each type seen */static int maxbtype = 0;static int maxktype = 0;/* Array of types seen so far in top-level call to `build_mangled_name'. Allocated and deallocated by caller. */static tree *typevec = NULL;static int typevec_size;/* Number of types interned by `build_mangled_name' so far. */static int maxtype = 0;/* Nonzero if we should not try folding parameter types. */static int nofold;/* This appears to be set to true if an underscore is required to be comcatenated before another number can be outputed. */static int numeric_output_need_bar;static __inline voidstart_squangling (){ if (flag_do_squangling) { nofold = 0; maxbtype = 0; maxktype = 0; maxbsize = 50; maxksize = 50; btypelist = (tree *)xmalloc (sizeof (tree) * maxbsize); ktypelist = (tree *)xmalloc (sizeof (tree) * maxksize); }}static __inline voidend_squangling (){ if (flag_do_squangling) { if (ktypelist) free (ktypelist); if (btypelist) free (btypelist); maxbsize = 0; maxksize = 0; maxbtype = 0; maxktype = 0; ktypelist = NULL; btypelist = NULL; }}/* Code to concatenate an asciified integer to a string. */static __inline voidicat (i) HOST_WIDE_INT i;{ unsigned HOST_WIDE_INT ui; /* Handle this case first, to go really quickly. For many common values, the result of ui/10 below is 1. */ if (i == 1) { OB_PUTC ('1'); return; } if (i >= 0) ui = i; else { OB_PUTC ('m'); ui = -i; } if (ui >= 10) icat (ui / 10); OB_PUTC ('0' + (ui % 10));}static voiddicat (lo, hi) HOST_WIDE_INT lo, hi;{ unsigned HOST_WIDE_INT ulo, uhi, qlo, qhi; if (hi >= 0) { uhi = hi; ulo = lo; } else { uhi = (lo == 0 ? -hi : -hi-1); ulo = -lo; } if (uhi == 0 && ulo < ((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1))) { icat (ulo); return; } /* Divide 2^HOST_WIDE_INT*uhi+ulo by 10. */ qhi = uhi / 10; uhi = uhi % 10; qlo = uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) / 5); qlo += ulo / 10; ulo = ulo % 10; ulo += uhi * (((unsigned HOST_WIDE_INT)1 << (HOST_BITS_PER_WIDE_INT - 1)) % 5) * 2; qlo += ulo / 10; ulo = ulo % 10; /* Quotient is 2^HOST_WIDE_INT*qhi+qlo, remainder is ulo. */ dicat (qlo, qhi); OB_PUTC ('0' + ulo);}/* Returns the index of TYPE in the typevec, or -1 if it's not there. */static __inline intold_backref_index (type) tree type;{ int tindex = 0; if (! is_back_referenceable_type (type)) return -1; /* The entry for this parm is at maxtype-1, so don't look there for something to repeat. */ for (tindex = 0; tindex < maxtype - 1; ++tindex) if (same_type_p (typevec[tindex], type)) break; if (tindex == maxtype - 1) return -1; return tindex;}/* Old mangling style: If TYPE has already been used in the parameter list, emit a backward reference and return non-zero; otherwise, return 0. NREPEATS is the number of repeats we've recorded of this type, or 0 if this is the first time we've seen it and we're just looking to see if it had been used before. */static __inline intflush_repeats (nrepeats, type) int nrepeats; tree type;{ int tindex = old_backref_index (type); if (tindex == -1) { my_friendly_assert (nrepeats == 0, 990316); return 0; } if (nrepeats > 1) { OB_PUTC ('N'); icat (nrepeats); if (nrepeats > 9) OB_PUTC ('_'); } else OB_PUTC ('T'); icat (tindex); if (tindex > 9) OB_PUTC ('_'); return 1;}/* Returns nonzero iff this is a type to which we will want to make back-references (using the `B' code). */static intis_back_referenceable_type (type) tree type;{ /* For some reason, the Java folks don't want back refs on these. */ if (TYPE_FOR_JAVA (type)) return 0; switch (TREE_CODE (type)) { case BOOLEAN_TYPE: if (!flag_do_squangling) /* Even though the mangling of this is just `b', we did historically generate back-references for it. */ return 1; /* Fall through. */ case INTEGER_TYPE: case REAL_TYPE: case VOID_TYPE: /* These types have single-character manglings, so there's no point in generating back-references. */ return 0; case TEMPLATE_TYPE_PARM: /* It would be a bit complex to demangle signatures correctly if we generated back-references to these, and the manglings of type parameters are short. */ return 0; default: return 1; }}/* Issue the squangling code indicating NREPEATS repetitions of TYPE, which was the last parameter type output. */static voidissue_nrepeats (nrepeats, type) int nrepeats; tree type;{ if (nrepeats == 1 && !is_back_referenceable_type (type)) /* For types whose manglings are short, don't bother using the repetition code if there's only one repetition, since the repetition code will be about as long as the ordinary mangling. */ build_mangled_name_for_type (type); else { OB_PUTC ('n'); icat (nrepeats); if (nrepeats > 9) OB_PUTC ('_'); }}/* Check to see if a tree node has been entered into the Kcode typelist. If not, add it. Returns -1 if it isn't found, otherwise returns the index. */static intcheck_ktype (node, add) tree node; int add;{ int x; tree localnode = node; if (ktypelist == NULL) return -1; if (TREE_CODE (node) == TYPE_DECL) localnode = TREE_TYPE (node); for (x=0; x < maxktype; x++) { if (same_type_p (localnode, ktypelist[x])) return x; } /* Didn't find it, so add it here. */ if (add) { if (maxksize <= maxktype) { maxksize = maxksize* 3 / 2; ktypelist = (tree *)xrealloc (ktypelist, sizeof (tree) * maxksize); } ktypelist[maxktype++] = localnode; } return -1;}static __inline intissue_ktype (decl) tree decl;{ int kindex; kindex = check_ktype (decl, FALSE); if (kindex != -1) { OB_PUTC ('K'); icat (kindex); if (kindex > 9) OB_PUTC ('_'); return TRUE; } return FALSE;} /* Build a representation for DECL, which may be an entity not at global scope. If so, a marker indicating that the name is qualified has already been output, but the qualifying context has not. */static voidbuild_overload_nested_name (decl) tree decl;{ tree context; if (ktypelist && issue_ktype (decl))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -