📄 method.c
字号:
} } } else { if (numeric_output_need_bar) { OB_PUTC ('_'); numeric_output_need_bar = 0; } icat (IDENTIFIER_LENGTH (name)); OB_PUTID (name); }}/* Given a list of parameters in PARMTYPES, create an unambiguous overload string. Should distinguish any type that C (or C++) can distinguish. I.e., pointers to functions are treated correctly. Caller must deal with whether a final `e' goes on the end or not. Any default conversions must take place before this function is called. BEGIN and END control initialization and finalization of the obstack where we build the string. */char *build_overload_name (parmtypes, begin, end) tree parmtypes; int begin, end;{ int just_one; tree parmtype; if (begin) OB_INIT (); numeric_output_need_bar = 0; if ((just_one = (TREE_CODE (parmtypes) != TREE_LIST))) { parmtype = parmtypes; goto only_one; } while (parmtypes) { parmtype = TREE_VALUE (parmtypes); only_one: if (! nofold && ! just_one) { /* Every argument gets counted. */ typevec[maxtype++] = parmtype; if (TREE_USED (parmtype) && parmtype == typevec[maxtype-2]) { nrepeats++; goto next; } if (nrepeats) flush_repeats (typevec[maxtype-2]); if (TREE_USED (parmtype)) { flush_repeats (parmtype); goto next; } /* Only cache types which take more than one character. */ if (parmtype != TYPE_MAIN_VARIANT (parmtype) || (TREE_CODE (parmtype) != INTEGER_TYPE && TREE_CODE (parmtype) != REAL_TYPE)) TREE_USED (parmtype) = 1; } if (TYPE_PTRMEMFUNC_P (parmtype)) parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype); if (TREE_READONLY (parmtype)) OB_PUTC ('C'); if (TREE_CODE (parmtype) == INTEGER_TYPE && TYPE_MAIN_VARIANT (parmtype) == unsigned_type (TYPE_MAIN_VARIANT (parmtype))) OB_PUTC ('U'); if (TYPE_VOLATILE (parmtype)) OB_PUTC ('V'); switch (TREE_CODE (parmtype)) { case OFFSET_TYPE: OB_PUTC ('O'); build_overload_name (TYPE_OFFSET_BASETYPE (parmtype), 0, 0); OB_PUTC ('_'); build_overload_name (TREE_TYPE (parmtype), 0, 0); break; case REFERENCE_TYPE: OB_PUTC ('R'); goto more; case ARRAY_TYPE:#if PARM_CAN_BE_ARRAY_TYPE { tree length; OB_PUTC ('A'); if (TYPE_DOMAIN (parmtype) == NULL_TREE) error ("pointer or reference to array of unknown bound in parm type"); else { length = array_type_nelts (parmtype); if (TREE_CODE (length) == INTEGER_CST) icat (TREE_INT_CST_LOW (length) + 1); } OB_PUTC ('_'); goto more; }#else OB_PUTC ('P'); goto more;#endif case POINTER_TYPE: OB_PUTC ('P'); more: build_overload_name (TREE_TYPE (parmtype), 0, 0); break; case FUNCTION_TYPE: case METHOD_TYPE: { tree firstarg = TYPE_ARG_TYPES (parmtype); /* Otherwise have to implement reentrant typevecs, unmark and remark types, etc. */ int old_nofold = nofold; nofold = 1; if (nrepeats) flush_repeats (typevec[maxtype-1]); /* @@ It may be possible to pass a function type in which is not preceded by a 'P'. */ if (TREE_CODE (parmtype) == FUNCTION_TYPE) { OB_PUTC ('F'); if (firstarg == NULL_TREE) OB_PUTC ('e'); else if (firstarg == void_list_node) OB_PUTC ('v'); else build_overload_name (firstarg, 0, 0); } else { int constp = TYPE_READONLY (TREE_TYPE (TREE_VALUE (firstarg))); int volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (firstarg))); OB_PUTC ('M'); firstarg = TREE_CHAIN (firstarg); build_overload_name (TYPE_METHOD_BASETYPE (parmtype), 0, 0); if (constp) OB_PUTC ('C'); if (volatilep) OB_PUTC ('V'); /* For cfront 2.0 compatibility. */ OB_PUTC ('F'); if (firstarg == NULL_TREE) OB_PUTC ('e'); else if (firstarg == void_list_node) OB_PUTC ('v'); else build_overload_name (firstarg, 0, 0); } /* Separate args from return type. */ OB_PUTC ('_'); build_overload_name (TREE_TYPE (parmtype), 0, 0); nofold = old_nofold; break; } case INTEGER_TYPE: parmtype = TYPE_MAIN_VARIANT (parmtype); if (parmtype == integer_type_node || parmtype == unsigned_type_node) OB_PUTC ('i'); else if (parmtype == long_integer_type_node || parmtype == long_unsigned_type_node) OB_PUTC ('l'); else if (parmtype == short_integer_type_node || parmtype == short_unsigned_type_node) OB_PUTC ('s'); else if (parmtype == signed_char_type_node) { OB_PUTC ('S'); OB_PUTC ('c'); } else if (parmtype == char_type_node || parmtype == unsigned_char_type_node) OB_PUTC ('c'); else if (parmtype == wchar_type_node) OB_PUTC ('w'); else if (parmtype == long_long_integer_type_node || parmtype == long_long_unsigned_type_node) OB_PUTC ('x');#if 0 /* it would seem there is no way to enter these in source code, yet. (mrs) */ else if (parmtype == long_long_long_integer_type_node || parmtype == long_long_long_unsigned_type_node) OB_PUTC ('q');#endif else my_friendly_abort (73); break; case BOOLEAN_TYPE: OB_PUTC ('b'); break; case REAL_TYPE: parmtype = TYPE_MAIN_VARIANT (parmtype); if (parmtype == long_double_type_node) OB_PUTC ('r'); else if (parmtype == double_type_node) OB_PUTC ('d'); else if (parmtype == float_type_node) OB_PUTC ('f'); else my_friendly_abort (74); break; case VOID_TYPE: if (! just_one) {#if 0 extern tree void_list_node; /* See if anybody is wasting memory. */ my_friendly_assert (parmtypes == void_list_node, 247);#endif /* This is the end of a parameter list. */ if (end) OB_FINISH (); return (char *)obstack_base (&scratch_obstack); } OB_PUTC ('v'); break; case ERROR_MARK: /* not right, but nothing is anyway */ break; /* have to do these */ case UNION_TYPE: case RECORD_TYPE: if (! just_one) /* Make this type signature look incompatible with AT&T. */ OB_PUTC ('G'); goto common; case ENUMERAL_TYPE: common: { tree name = TYPE_NAME (parmtype); int i = 1; if (TREE_CODE (name) == TYPE_DECL) { tree context = name; /* If DECL_ASSEMBLER_NAME has been set properly, use it. */ if (DECL_ASSEMBLER_NAME (context) != DECL_NAME (context)) { OB_PUTID (DECL_ASSEMBLER_NAME (context)); break; } while (DECL_CONTEXT (context)) { i += 1; context = DECL_CONTEXT (context); if (TREE_CODE_CLASS (TREE_CODE (context)) == 't') context = TYPE_NAME (context); } name = DECL_NAME (name); } my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 248); if (i > 1) { OB_PUTC ('Q'); if (i > 9) OB_PUTC ('_'); icat (i); if (i > 9) OB_PUTC ('_'); numeric_output_need_bar = 0; build_overload_nested_name (TYPE_MAIN_DECL (parmtype)); } else build_overload_identifier (name); break; } case UNKNOWN_TYPE: /* This will take some work. */ OB_PUTC ('?'); break; case TEMPLATE_TYPE_PARM: case TEMPLATE_CONST_PARM: case UNINSTANTIATED_P_TYPE: /* 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); } break; default: my_friendly_abort (75); } next: if (just_one) break; parmtypes = TREE_CHAIN (parmtypes); } if (! just_one) { if (nrepeats) flush_repeats (typevec[maxtype-1]); /* To get here, parms must end with `...'. */ OB_PUTC ('e'); } if (end) OB_FINISH (); return (char *)obstack_base (&scratch_obstack);}treebuild_static_name (basetype, name) tree basetype, name;{ char *basename = build_overload_name (basetype, 1, 1); char *buf = (char *) alloca (IDENTIFIER_LENGTH (name) + sizeof (STATIC_NAME_FORMAT) + strlen (basename)); sprintf (buf, STATIC_NAME_FORMAT, basename, IDENTIFIER_POINTER (name)); return get_identifier (buf);} /* Generate an identifier that encodes the (ANSI) exception TYPE. *//* This should be part of `ansi_opname', or at least be defined by the std. */#define EXCEPTION_NAME_PREFIX "__ex"#define EXCEPTION_NAME_LENGTH 4treecplus_exception_name (type) tree type;{ OB_INIT (); OB_PUTS (EXCEPTION_NAME_PREFIX); return get_identifier (build_overload_name (type, 0, 1));}/* Change the name of a function definition so that it may be overloaded. NAME is the name of the function to overload, PARMS is the parameter list (which determines what name the final function obtains). FOR_METHOD is 1 if this overload is being performed for a method, rather than a function type. It is 2 if this overload is being performed for a constructor. */treebuild_decl_overload (dname, parms, for_method) tree dname; tree parms; int for_method;{ char *name = IDENTIFIER_POINTER (dname); /* member operators new and delete look like methods at this point. */ if (! for_method && parms != NULL_TREE && TREE_CODE (parms) == TREE_LIST) { if (dname == ansi_opname[(int) DELETE_EXPR]) return get_identifier ("__builtin_delete"); else if (dname == ansi_opname[(int) VEC_DELETE_EXPR]) return get_identifier ("__builtin_vec_delete"); else if (TREE_CHAIN (parms) == void_list_node) { if (dname == ansi_opname[(int) NEW_EXPR]) return get_identifier ("__builtin_new"); else if (dname == ansi_opname[(int) VEC_NEW_EXPR]) return get_identifier ("__builtin_vec_new"); } } OB_INIT (); if (for_method != 2) OB_PUTCP (name); /* Otherwise, we can divine that this is a constructor, and figure out its name without any extra encoding. */ OB_PUTC2 ('_', '_'); if (for_method) {#if 0 /* We can get away without doing this. */ OB_PUTC ('M');#endif { tree this_type = TREE_VALUE (parms); if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ parms = temp_tree_cons (NULL_TREE, SIGNATURE_TYPE (this_type), TREE_CHAIN (parms)); else parms = temp_tree_cons (NULL_TREE, TREE_TYPE (this_type), TREE_CHAIN (parms)); } } else OB_PUTC ('F'); if (parms == NULL_TREE) OB_PUTC2 ('e', '\0'); else if (parms == void_list_node) OB_PUTC2 ('v', '\0'); else { ALLOCATE_TYPEVEC (parms); nofold = 0; if (for_method) { build_overload_name (TREE_VALUE (parms), 0, 0); typevec[maxtype++] = TREE_VALUE (parms); TREE_USED (TREE_VALUE (parms)) = 1; if (TREE_CHAIN (parms)) build_overload_name (TREE_CHAIN (parms), 0, 1); else OB_PUTC2 ('e', '\0'); } else build_overload_name (parms, 0, 1); DEALLOCATE_TYPEVEC (parms); } { tree n = get_identifier (obstack_base (&scratch_obstack)); if (IDENTIFIER_OPNAME_P (dname)) IDENTIFIER_OPNAME_P (n) = 1; return n; }}/* Build an overload name for the type expression TYPE. */treebuild_typename_overload (type) tree type;{ tree id; OB_INIT (); OB_PUTID (ansi_opname[(int) TYPE_EXPR]); nofold = 1; build_overload_name (type, 0, 1); id = get_identifier (obstack_base (&scratch_obstack)); IDENTIFIER_OPNAME_P (id) = 1;#if 0 IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);#endif TREE_TYPE (id) = type; return id;}#ifndef NO_DOLLAR_IN_LABEL#define T_DESC_FORMAT "TD$"#define I_DESC_FORMAT "ID$"#define M_DESC_FORMAT "MD$"#else#if !defined(NO_DOT_IN_LABEL)#define T_DESC_FORMAT "TD."#define I_DESC_FORMAT "ID."#define M_DESC_FORMAT "MD."#else#define T_DESC_FORMAT "__t_desc_"#define I_DESC_FORMAT "__i_desc_"#define M_DESC_FORMAT "__m_desc_"#endif#endif/* Build an overload name for the type expression TYPE. */treebuild_t_desc_overload (type) tree type;{ OB_INIT (); OB_PUTS (T_DESC_FORMAT); nofold = 1;#if 0 /* Use a different format if the type isn't defined yet. */ if (TYPE_SIZE (type) == NULL_TREE) { char *p; int changed; for (p = tname; *p; p++) if (isupper (*p)) { changed = 1; *p = tolower (*p); } /* If there's no change, we have an inappropriate T_DESC_FORMAT. */ my_friendly_assert (changed != 0, 249); }#endif build_overload_name (type, 0, 1); return get_identifier (obstack_base (&scratch_obstack));}/* Top-level interface to explicit overload requests. Allow NAME to be overloaded. Error if NAME is already declared for the current scope. Warning if function is redundantly overloaded. */voiddeclare_overloaded (name) tree name;{#ifdef NO_AUTO_OVERLOAD if (is_overloaded (name)) warning ("function `%s' already declared overloaded", IDENTIFIER_POINTER (name)); else if (IDENTIFIER_GLOBAL_VALUE (name)) error ("overloading function `%s' that is already defined", IDENTIFIER_POINTER (name)); else { TREE_OVERLOADED (name) = 1; IDENTIFIER_GLOBAL_VALUE (name) = build_tree_list (name, NULL_TREE); TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name)) = unknown_type_node; }#else if (current_lang_name == lang_name_cplusplus) { if (0) warning ("functions are implicitly overloaded in C++"); } else if (current_lang_name == lang_name_c) error ("overloading function `%s' cannot be done in C language context"); else my_friendly_abort (76);#endif}#ifdef NO_AUTO_OVERLOAD/* Check to see if NAME is overloaded. For first approximation, check to see if its TREE_OVERLOADED is set. This is used on IDENTIFIER nodes. */intis_overloaded (name) tree name;{ /* @@ */ return (TREE_OVERLOADED (name) && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -