📄 method.c
字号:
/* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 89, 92, 93, 94, 1995 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 PARM_CAN_BE_ARRAY_TYPE#define PARM_CAN_BE_ARRAY_TYPE 1#endif/* Handle method declarations. */#include <stdio.h>#include "config.h"#include "tree.h"#include "cp-tree.h"#include "class.h"#include "obstack.h"#include <ctype.h>#include "rtl.h"#include "expr.h"#include "output.h"#include "hard-reg-set.h"#include "flags.h"/* TREE_LIST of the current inline functions that need to be processed. */struct pending_inline *pending_inlines;#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;# 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])#ifdef NO_AUTO_OVERLOADint is_overloaded ();#endifvoidinit_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, 0)) method = TREE_VEC_ELT (method, 0); else method = TREE_VEC_ELT (method, 1); } 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); } /* Allow this decl to be seen in global scope. Don't do this for local class methods, though. */ if (! current_function_decl) IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (method)) = method; } 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); } /* Allow this decl to be seen in global scope */ if (! current_function_decl) IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (fndecl)) = fndecl; } friend_list = TREE_CHAIN (friend_list); }}/* Report an argument type mismatch between the best declared function we could find and the current argument list that we have. */voidreport_type_mismatch (cp, parmtypes, name_kind) struct candidate *cp; tree parmtypes; char *name_kind;{ int i = cp->u.bad_arg; tree ttf, tta; char *tmp_firstobj; switch (i) { case -4: my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240); cp_error ("type unification failed for function template `%#D'", cp->function); return; case -2: cp_error ("too few arguments for %s `%#D'", name_kind, cp->function); return; case -1: cp_error ("too many arguments for %s `%#D'", name_kind, cp->function); return; case 0: if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE) break; case -3: /* Happens when the implicit object parameter is rejected. */ my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))), 241); cp_error ("call to non-const %s `%#D' with const object", name_kind, cp->function); return; } ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function)); tta = parmtypes; while (i-- > 0) { ttf = TREE_CHAIN (ttf); tta = TREE_CHAIN (tta); } OB_INIT (); OB_PUTS ("bad argument "); sprintf (digit_buffer, "%d", cp->u.bad_arg - (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE) + 1); OB_PUTCP (digit_buffer); OB_PUTS (" for function `"); OB_PUTCP (decl_as_string (cp->function, 1)); OB_PUTS ("' (type was "); /* Reset `i' so that type printing routines do the right thing. */ if (tta) { enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta))); if (code == ERROR_MARK) OB_PUTS ("(failed type instantiation)"); else { i = (code == FUNCTION_TYPE || code == METHOD_TYPE); OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1)); } } else OB_PUTS ("void"); OB_PUTC (')'); OB_FINISH (); tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack)); bcopy (obstack_base (&scratch_obstack), tmp_firstobj, obstack_object_size (&scratch_obstack)); error (tmp_firstobj);}/* Here is where overload code starts. *//* Array of types seen so far in top-level call to `build_overload_name'. Allocated and deallocated by caller. */static tree *typevec;/* Number of types interned by `build_overload_name' so far. */static int maxtype;/* Number of occurrences of last type seen. */static int nrepeats;/* Nonzero if we should not try folding parameter types. */static int nofold;#define ALLOCATE_TYPEVEC(PARMTYPES) \ do { maxtype = 0, nrepeats = 0; \ typevec = (tree *)alloca (list_length (PARMTYPES) * sizeof (tree)); } while (0)#define DEALLOCATE_TYPEVEC(PARMTYPES) \ do { tree t = (PARMTYPES); \ while (t) { TREE_USED (TREE_VALUE (t)) = 0; t = TREE_CHAIN (t); } \ } while (0)/* Code to concatenate an asciified integer to a string. */static#ifdef __GNUC____inline#endifvoidicat (i) int i;{ /* Handle this case first, to go really quickly. For many common values, the result of i/10 below is 1. */ if (i == 1) { OB_PUTC ('1'); return; } if (i < 0) { OB_PUTC ('m'); i = -i; } if (i < 10) OB_PUTC ('0' + i); else { icat (i / 10); OB_PUTC ('0' + (i % 10)); }}static#ifdef __GNUC____inline#endifvoidflush_repeats (type) tree type;{ int tindex = 0; while (typevec[tindex] != type) tindex++; if (nrepeats > 1) { OB_PUTC ('N'); icat (nrepeats); if (nrepeats > 9) OB_PUTC ('_'); } else OB_PUTC ('T'); nrepeats = 0; icat (tindex); if (tindex > 9) OB_PUTC ('_');}static int numeric_output_need_bar;static void build_overload_identifier ();static voidbuild_overload_nested_name (decl) tree decl;{ if (DECL_CONTEXT (decl)) { tree context = DECL_CONTEXT (decl); if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') context = TYPE_MAIN_DECL (context); build_overload_nested_name (context); } if (TREE_CODE (decl) == FUNCTION_DECL) { tree name = DECL_ASSEMBLER_NAME (decl); char *label; extern int var_labelno; ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), var_labelno); var_labelno++; if (numeric_output_need_bar) { OB_PUTC ('_'); numeric_output_need_bar = 0; } icat (strlen (label)); OB_PUTCP (label); } else /* TYPE_DECL */ { tree name = DECL_NAME (decl); build_overload_identifier (name); }}/* Encoding for an INTEGER_CST value. */static voidbuild_overload_int (value) tree value;{ my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT) { if (tree_int_cst_lt (value, integer_zero_node)) { OB_PUTC ('m'); value = build_int_2 (~ TREE_INT_CST_LOW (value), - TREE_INT_CST_HIGH (value)); } if (TREE_INT_CST_HIGH (value) != (TREE_INT_CST_LOW (value) >> (HOST_BITS_PER_WIDE_INT - 1))) { /* need to print a DImode value in decimal */ sorry ("conversion of long long as PT parameter"); } /* else fall through to print in smaller mode */ } /* Wordsize or smaller */ icat (TREE_INT_CST_LOW (value));}static voidbuild_overload_value (type, value) tree type, value;{ while (TREE_CODE (value) == NON_LVALUE_EXPR || TREE_CODE (value) == NOP_EXPR) value = TREE_OPERAND (value, 0); my_friendly_assert (TREE_CODE (type) == PARM_DECL, 242); type = TREE_TYPE (type); if (numeric_output_need_bar) { OB_PUTC ('_'); numeric_output_need_bar = 0; } if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE) { /* Handle a pointer to data member as a template instantiation parameter, boy, what fun! */ type = integer_type_node; if (TREE_CODE (value) != INTEGER_CST) { sorry ("unknown pointer to member constant"); return; } } if (TYPE_PTRMEMFUNC_P (type)) type = TYPE_PTRMEMFUNC_FN_TYPE (type); switch (TREE_CODE (type)) { case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: { build_overload_int (value); numeric_output_need_bar = 1; return; }#ifndef REAL_IS_NOT_DOUBLE case REAL_TYPE: { REAL_VALUE_TYPE val; char *bufp = digit_buffer; extern char *index (); my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); val = TREE_REAL_CST (value); if (val < 0) { val = -val; *bufp++ = 'm'; } sprintf (bufp, "%e", val); bufp = (char *) index (bufp, 'e'); if (!bufp) strcat (digit_buffer, "e0"); else { char *p; bufp++; if (*bufp == '-') { *bufp++ = 'm'; } p = bufp; if (*p == '+') p++; while (*p == '0') p++; if (*p == 0) { *bufp++ = '0'; *bufp = 0; } else if (p != bufp) { while (*p) *bufp++ = *p++; *bufp = 0; } } OB_PUTCP (digit_buffer); numeric_output_need_bar = 1; return; }#endif case POINTER_TYPE: if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE && TREE_CODE (value) != ADDR_EXPR) { if (TREE_CODE (value) == CONSTRUCTOR) { /* This is dangerous code, crack built up pointer to members. */ tree args = CONSTRUCTOR_ELTS (value); tree a1 = TREE_VALUE (args); tree a2 = TREE_VALUE (TREE_CHAIN (args)); tree a3 = CONSTRUCTOR_ELTS (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)))); a3 = TREE_VALUE (a3); STRIP_NOPS (a3); if (TREE_CODE (a1) == INTEGER_CST && TREE_CODE (a2) == INTEGER_CST) { build_overload_int (a1); OB_PUTC ('_'); build_overload_int (a2); OB_PUTC ('_'); if (TREE_CODE (a3) == ADDR_EXPR) { a3 = TREE_OPERAND (a3, 0); if (TREE_CODE (a3) == FUNCTION_DECL) { numeric_output_need_bar = 0; build_overload_identifier (DECL_ASSEMBLER_NAME (a3)); return; } } else if (TREE_CODE (a3) == INTEGER_CST) { OB_PUTC ('i'); build_overload_int (a3); numeric_output_need_bar = 1; return; } } } sorry ("template instantiation with pointer to method that is too complex"); return; } if (TREE_CODE (value) == INTEGER_CST) { build_overload_int (value); numeric_output_need_bar = 1; return; } value = TREE_OPERAND (value, 0); if (TREE_CODE (value) == VAR_DECL) { my_friendly_assert (DECL_NAME (value) != 0, 245); build_overload_identifier (DECL_NAME (value)); return; } else if (TREE_CODE (value) == FUNCTION_DECL) { my_friendly_assert (DECL_NAME (value) != 0, 246); build_overload_identifier (DECL_NAME (value)); return; } else my_friendly_abort (71); break; /* not really needed */ default: sorry ("conversion of %s as template parameter", tree_code_name [(int) TREE_CODE (type)]); my_friendly_abort (72); }}static voidbuild_overload_identifier (name) tree name;{ if (IDENTIFIER_TEMPLATE (name)) { tree template, parmlist, arglist, tname; int i, nparms; template = IDENTIFIER_TEMPLATE (name); arglist = TREE_VALUE (template); template = TREE_PURPOSE (template); tname = DECL_NAME (template); parmlist = DECL_ARGUMENTS (template); nparms = TREE_VEC_LENGTH (parmlist); OB_PUTC ('t'); icat (IDENTIFIER_LENGTH (tname)); OB_PUTID (tname); icat (nparms); for (i = 0; i < nparms; i++) { tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); tree arg = TREE_VEC_ELT (arglist, i); if (TREE_CODE (parm) == TYPE_DECL) { /* This parameter is a type. */ OB_PUTC ('Z'); build_overload_name (arg, 0, 0); } else { parm = tsubst (parm, &TREE_VEC_ELT (arglist, 0), TREE_VEC_LENGTH (arglist), NULL_TREE); /* It's a PARM_DECL. */ build_overload_name (TREE_TYPE (parm), 0, 0); build_overload_value (parm, arg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -