method.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,227 行 · 第 1/4 页
C
2,227 行
/* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 89, 92-96, 1997 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 "config.h"#include <stdio.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"#ifdef HAVE_STRING_H#include <string.h>#elseextern char *index ();#endif/* 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 void flush_repeats PROTO((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 char *thunk_printable_name PROTO((tree));static void do_build_assign_ref PROTO((tree));static void do_build_copy_constructor PROTO((tree));static tree largest_union_member PROTO((tree));static tree build_decl_overload_real PROTO((tree, tree, tree, tree, tree, int)); static void build_template_parm_names PROTO((tree, tree));static void build_underscore_int PROTO((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); } /* 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); if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes)))) && ! TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (cp->function)))))) cp_error ("call to non-volatile %s `%#D' with volatile object", name_kind, cp->function); else 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) 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);}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 voidbuild_overload_nested_name (decl) tree decl;{ if (DECL_CONTEXT (decl)) { tree context = DECL_CONTEXT (decl); /* For a template type parameter, we want to output an 'Xn' rather than 'T' or some such. */ if (TREE_CODE (context) == TEMPLATE_TYPE_PARM) build_overload_name (context, 0, 0); else { if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') context = TYPE_NAME (context); build_overload_nested_name (context); } } if (TREE_CODE (decl) == FUNCTION_DECL) { tree name = DECL_ASSEMBLER_NAME (decl); char *label; ASM_FORMAT_PRIVATE_NAME (label, IDENTIFIER_POINTER (name), static_labelno); static_labelno++; if (numeric_output_need_bar) OB_PUTC ('_'); icat (strlen (label)); OB_PUTCP (label); numeric_output_need_bar = 1; } else /* TYPE_DECL */ build_overload_identifier (decl);}static voidbuild_underscore_int (i) int i;{ if (i > 9) OB_PUTC ('_'); icat (i); if (i > 9) OB_PUTC ('_');}/* Encoding for an INTEGER_CST value. */static voidbuild_overload_int (value, in_template) tree value; int in_template;{ if (in_template && TREE_CODE (value) != INTEGER_CST) /* We don't ever want this output, but it's inconvenient not to be able to build the string. This should cause assembler errors we'll notice. */ { static int n; sprintf (digit_buffer, " *%d", n++); OB_PUTCP (digit_buffer); return; } my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243); if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT) { 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 */ dicat (TREE_INT_CST_LOW (value), TREE_INT_CST_HIGH (value)); return; } /* else fall through to print in smaller mode */ } /* Wordsize or smaller */ icat (TREE_INT_CST_LOW (value));}static voidbuild_overload_value (type, value, in_template) tree type, value; int in_template;{ 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 (value) == TEMPLATE_CONST_PARM) { OB_PUTC ('Y'); build_underscore_int (TEMPLATE_CONST_IDX (value)); build_underscore_int (TEMPLATE_CONST_LEVEL (value)); return; } 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, in_template); numeric_output_need_bar = 1; return; } case REAL_TYPE: { REAL_VALUE_TYPE val; char *bufp = digit_buffer; pedwarn ("ANSI C++ forbids floating-point template arguments"); my_friendly_assert (TREE_CODE (value) == REAL_CST, 244); val = TREE_REAL_CST (value); if (REAL_VALUE_ISNAN (val)) { sprintf (bufp, "NaN"); } else { if (REAL_VALUE_NEGATIVE (val)) { val = REAL_VALUE_NEGATE (val); *bufp++ = 'm'; } if (REAL_VALUE_ISINF (val)) { sprintf (bufp, "Infinity"); } else { REAL_VALUE_TO_DECIMAL (val, "%.20e", bufp); 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')
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?