📄 method.c
字号:
break; case BOOLEAN_TYPE: OB_PUTC ('b'); break; case REAL_TYPE: if (parmtype == long_double_type_node) OB_PUTC ('r'); else if (parmtype == double_type_node || parmtype == java_double_type_node) OB_PUTC ('d'); else if (parmtype == float_type_node || parmtype == java_float_type_node) OB_PUTC ('f'); else my_friendly_abort (74); break; case COMPLEX_TYPE: OB_PUTC ('J'); build_mangled_name_for_type (TREE_TYPE (parmtype)); break; case VOID_TYPE: 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 (extra_Gcode) OB_PUTC ('G'); /* make it look incompatible with AT&T */ /* drop through into next case */ } case ENUMERAL_TYPE: { tree name = TYPE_NAME (parmtype); my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248); build_qualified_name (name); break; } case UNKNOWN_TYPE: /* This will take some work. */ OB_PUTC ('?'); break; case TEMPLATE_TEMPLATE_PARM: /* Find and output the original template parameter declaration. */ if (TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (parmtype)) { build_mangled_template_parm_index ("tzX", TEMPLATE_TYPE_PARM_INDEX (parmtype)); build_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_TI_TEMPLATE (parmtype)), TYPE_TI_ARGS (parmtype)); } else { build_mangled_template_parm_index ("ZzX", TEMPLATE_TYPE_PARM_INDEX (parmtype)); build_template_template_parm_names (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype))); } break; case TEMPLATE_TYPE_PARM: build_mangled_template_parm_index ("X", TEMPLATE_TYPE_PARM_INDEX (parmtype)); break; case TYPENAME_TYPE: /* When mangling the type of a function template whose declaration looks like: template <class T> void foo(typename T::U) we have to mangle these. */ build_qualified_name (parmtype); break; default: my_friendly_abort (75); }}/* Produce the mangling for a variable named NAME in CONTEXT, which can be either a class TYPE or a FUNCTION_DECL. */treebuild_static_name (context, name) tree context, name;{ OB_INIT (); numeric_output_need_bar = 0; start_squangling ();#ifdef JOINER OB_PUTC ('_'); build_qualified_name (context); OB_PUTC (JOINER);#else OB_PUTS ("__static_"); build_qualified_name (context); OB_PUTC ('_');#endif OB_PUTID (name); OB_FINISH (); end_squangling (); return get_identifier ((char *)obstack_base (&scratch_obstack));}/* FOR_METHOD should be 1 if the declaration in question is for a member of a class (including a static member) and 2 if the declaration is for a constructor. */tree build_decl_overload_real (dname, parms, ret_type, tparms, targs, for_method) tree dname; tree parms; tree ret_type; tree tparms; tree targs; 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 && TREE_CHAIN (parms) == void_list_node) { 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"); 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"); } start_squangling (); 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 ('_', '_'); numeric_output_need_bar = 0; if (tparms) { OB_PUTC ('H'); build_template_parm_names (tparms, targs); OB_PUTC ('_'); } else if (!for_method && current_namespace == global_namespace) /* XXX this works only if we call this in the same namespace as the declaration. Unfortunately, we don't have the _DECL, only its name */ OB_PUTC ('F'); if (!for_method && current_namespace != global_namespace) /* qualify with namespace */ build_qualified_name (current_namespace); if (parms == NULL_TREE) OB_PUTC ('e'); else if (parms == void_list_node) OB_PUTC ('v'); else { if (!flag_do_squangling) { /* Allocate typevec array. */ maxtype = 0; typevec_size = list_length (parms); if (!for_method && current_namespace != global_namespace) /* The namespace of a global function needs one slot. */ typevec_size++; typevec = (tree *)alloca (typevec_size * sizeof (tree)); } nofold = 0; if (for_method) { tree this_type = TREE_VALUE (parms); if (TREE_CODE (this_type) == RECORD_TYPE) /* a signature pointer */ this_type = SIGNATURE_TYPE (this_type); else this_type = TREE_TYPE (this_type); build_mangled_name_for_type (this_type); if (!flag_do_squangling) { my_friendly_assert (maxtype < typevec_size, 387); typevec[maxtype++] = this_type; } if (TREE_CHAIN (parms)) build_mangled_name (TREE_CHAIN (parms), 0, 0); else OB_PUTC ('e'); } else { /* the namespace qualifier for a global function will count as type */ if (current_namespace != global_namespace && !flag_do_squangling) { my_friendly_assert (maxtype < typevec_size, 387); typevec[maxtype++] = current_namespace; } build_mangled_name (parms, 0, 0); } if (!flag_do_squangling) /* Deallocate typevec array. */ typevec = NULL; } if (ret_type != NULL_TREE && for_method != 2) { /* Add the return type. */ OB_PUTC ('_'); build_mangled_name_for_type (ret_type); } OB_FINISH (); end_squangling (); { tree n = get_identifier (obstack_base (&scratch_obstack)); if (IDENTIFIER_OPNAME_P (dname)) IDENTIFIER_OPNAME_P (n) = 1; return n; }}/* 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;{ return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE, NULL_TREE, for_method); }/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */voidset_mangled_name_for_decl (decl) tree decl;{ tree parm_types; if (processing_template_decl) /* There's no need to mangle the name of a template function. */ return; parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); if (DECL_STATIC_FUNCTION_P (decl)) parm_types = hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)), parm_types); else /* The only member functions whose type is a FUNCTION_TYPE, rather than a METHOD_TYPE, should be static members. */ my_friendly_assert (!DECL_CONTEXT (decl) || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl))) || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE, 0); DECL_ASSEMBLER_NAME (decl) = build_decl_overload (DECL_NAME (decl), parm_types, DECL_FUNCTION_MEMBER_P (decl) + DECL_CONSTRUCTOR_P (decl));}/* 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; start_squangling (); build_mangled_name (type, 0, 1); id = get_identifier (obstack_base (&scratch_obstack)); IDENTIFIER_OPNAME_P (id) = 1;#if 0 IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);#endif TREE_TYPE (id) = type; end_squangling (); return id;}treebuild_overload_with_type (name, type) tree name, type;{ OB_INIT (); OB_PUTID (name); nofold = 1; start_squangling (); build_mangled_name (type, 0, 1); end_squangling (); return get_identifier (obstack_base (&scratch_obstack));}treeget_id_2 (name, name2) char *name; tree name2;{ OB_INIT (); OB_PUTCP (name); OB_PUTID (name2); OB_FINISH (); return get_identifier (obstack_base (&scratch_obstack));}/* Print a binfo path T, starting with the most derived class. If OMIT_LAST is set, drop and return the most derived class. */static treebuild_base_path (t, omit_last) tree t; int omit_last;{ tree ret = NULL_TREE; if (BINFO_INHERITANCE_CHAIN (t)) ret = build_base_path (BINFO_INHERITANCE_CHAIN (t), omit_last); else if (omit_last) return t; process_overload_item (BINFO_TYPE (t), 0); return ret;}/* Return a mangled name for a vlist vtable, using the path of both BASE and VBASE. */treeget_vlist_vtable_id (base, vbase) tree base, vbase;{ tree last; OB_INIT (); OB_PUTS (VCTABLE_NAME); build_base_path (base, 0); OB_PUTC ('_'); /* Since the base path should end where the vbase path starts, we can omit the most-derived class in the vbase path. Check below that this really happens. */ last = build_base_path (vbase, 1); my_friendly_assert (BINFO_TYPE (last) == BINFO_TYPE (base), 990402); OB_FINISH (); return get_identifier (obstack_base (&scratch_obstack));} /* Returns a DECL_ASSEMBLER_NAME for the destructor of type TYPE. If HAS_VLIST is set, also add the vlist argument. */treebuild_destructor_name (type, has_vlist) tree type; int has_vlist;{ OB_INIT (); OB_PUTS (DESTRUCTOR_DECL_PREFIX); start_squangling (); build_mangled_name_for_type (type); /* If we need backwards compatibility, we can get aways by not linking type-safely, as the dtor will check whether the argument was provided. */ if (has_vlist && !flag_vtable_thunks_compat) OB_PUTS (VLIST_TYPE_NAME); OB_FINISH (); end_squangling (); return get_identifier (obstack_base (&scratch_obstack));}/* Given a tree_code CODE, and some arguments (at least one), attempt to use an overloaded operator on the arguments. For unary operators, only the first argument need be checked. For binary operators, both arguments may need to be checked. Member functions can convert class references to class pointers, for one-level deep indirection. More than that is not supported. Operators [](), ()(), and ->() must be member functions. We call function call building calls with LOOKUP_COMPLAIN if they are our only hope. This is true when we see a vanilla operator applied to something of aggregate type. If this fails, we are free to return `error_mark_node', because we will have reported the error. Operators NEW and DELETE overload in funny ways: operator new takes a single `size' parameter, and operator delete takes a pointer to the storage being deleted. When overloading these operators, success is assumed. If there is a failure, report an error message and return `error_mark_node'. *//* NOSTRICT */treebuild_opfncall (code, flags, xarg1, xarg2, arg3) enum tree_code code; int flags; tree xarg1, xarg2, arg3;{ return build_new_op (code, flags, xarg1, xarg2, arg3);}/* This function takes an identifier, ID, and attempts to figure out what it means. There are a number of possible scenarios, presented in increasing order of hair: 1) not in a class's scope 2) in class's scope, member name of the class's method 3) in class's scope, but not a member name of the class 4) in class's scope, member name of a class's variable NAME is $1 from the bison rule. It is an IDENTIFIER_NODE. VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1) As a last ditch, try to look up the name as a label and return that address. Values which are declared as being of REFERENCE_TYPE are automatically dereferenced here (as a hack to make the compiler faster). */treehack_identifier (value, name) tree value, name;{ tree type; if (value == error_mark_node) { if (current_class_name) { tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), name, 1); if (fields == error_mark_node) return error_mark_node; if (fields) { tree fndecl; fndecl = TREE_VALUE (fields); my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251); /* I could not trigger this code. MvL */ my_friendly_abort (980325);#ifdef DEAD if (DECL_CHAIN (fndecl) == NULL_TREE) { warning ("methods cannot be converted to function pointers"); return fndecl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -