📄 cp-decl2.c
字号:
&& DECL_SIZE (decl) == DECL_SIZE (anon_union_decl)) { main_decl = decl; } else { /* ??? This causes there to be no debug info written out about this decl. */ TREE_ASM_WRITTEN (decl) = 1; } DECL_INITIAL (decl) = NULL_TREE; /* If there's a cleanup to do, it belongs in the TREE_PURPOSE of the following TREE_LIST. */ elems = tree_cons (NULL_TREE, decl, elems); TREE_TYPE (elems) = type; field = TREE_CHAIN (field); } if (static_p) { make_decl_rtl (main_decl, 0, global_bindings_p ()); DECL_RTL (anon_union_decl) = DECL_RTL (main_decl); } /* The following call assumes that there are never any cleanups for anonymous unions--a reasonable assumption. */ expand_anon_union_decl (anon_union_decl, NULL_TREE, elems); if (flag_cadillac) cadillac_finish_anon_union (anon_union_decl);}/* Finish and output a table which is generated by the compiler. NAME is the name to give the table. TYPE is the type of the table entry. INIT is all the elements in the table. PUBLICP is non-zero if this table should be given external visibility. */treefinish_table (name, type, init, publicp) tree name, type, init; int publicp;{ tree itype, atype, decl; static tree empty_table; int is_empty = 0; tree asmspec; itype = build_index_type (size_int (list_length (init) - 1)); atype = build_cplus_array_type (type, itype); layout_type (atype); if (TREE_VALUE (init) == integer_zero_node && TREE_CHAIN (init) == NULL_TREE) { if (empty_table == NULL_TREE) { empty_table = get_temp_name (atype, 1); init = build (CONSTRUCTOR, atype, NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; DECL_INITIAL (empty_table) = init; asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), IDENTIFIER_POINTER (DECL_NAME (empty_table))); finish_decl (empty_table, init, asmspec, 0); } is_empty = 1; } if (name == NULL_TREE) { if (is_empty) return empty_table; decl = get_temp_name (atype, 1); } else { decl = build_decl (VAR_DECL, name, atype); decl = pushdecl (decl); TREE_STATIC (decl) = 1; } if (is_empty == 0) { TREE_PUBLIC (decl) = publicp; init = build (CONSTRUCTOR, atype, NULL_TREE, init); TREE_CONSTANT (init) = 1; TREE_STATIC (init) = 1; DECL_INITIAL (decl) = init; asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)), IDENTIFIER_POINTER (DECL_NAME (decl))); } else { /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */ DECL_EXTERNAL (decl) = 1; TREE_STATIC (decl) = 0; init = 0; asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), IDENTIFIER_POINTER (DECL_NAME (empty_table))); } finish_decl (decl, init, asmspec, 0); return decl;}/* Finish processing a builtin type TYPE. It's name is NAME, its fields are in the array FIELDS. LEN is the number of elements in FIELDS. It is given the same alignment as ALIGN_TYPE. */voidfinish_builtin_type (type, name, fields, len, align_type) tree type; char *name; tree fields[]; int len; tree align_type;{ register int i; TYPE_FIELDS (type) = fields[0]; for (i = 0; i < len; i++) { layout_type (TREE_TYPE (fields[i])); DECL_FIELD_CONTEXT (fields[i]) = type; TREE_CHAIN (fields[i]) = fields[i+1]; } DECL_FIELD_CONTEXT (fields[i]) = type; DECL_CLASS_CONTEXT (fields[i]) = type; TYPE_ALIGN (type) = TYPE_ALIGN (align_type); layout_type (type);#if 0 /* not yet, should get fixed properly later */ TYPE_NAME (type) = make_type_decl (get_identifier (name), type);#else TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);#endif layout_decl (TYPE_NAME (type), 0);}/* Auxiliary functions to make type signatures for `operator new' and `operator delete' correspond to what compiler will be expecting. */extern tree sizetype;treecoerce_new_type (ctype, type) tree ctype; tree type;{ int e1 = 0, e2 = 0; if (TREE_CODE (type) == METHOD_TYPE) type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); if (TREE_TYPE (type) != ptr_type_node) e1 = 1, error ("`operator new' must return type `void *'"); /* Technically the type must be `size_t', but we may not know what that is. */ if (TYPE_ARG_TYPES (type) == NULL_TREE) e1 = 1, error ("`operator new' takes type `size_t' parameter"); else if (TREE_CODE (TREE_VALUE (TYPE_ARG_TYPES (type))) != INTEGER_TYPE || TYPE_PRECISION (TREE_VALUE (TYPE_ARG_TYPES (type))) != TYPE_PRECISION (sizetype)) e2 = 1, error ("`operator new' takes type `size_t' as first parameter"); if (e2) type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type)))); else if (e1) type = build_function_type (ptr_type_node, TYPE_ARG_TYPES (type)); return type;}treecoerce_delete_type (ctype, type) tree ctype; tree type;{ int e1 = 0, e2 = 0, e3 = 0; tree arg_types = TYPE_ARG_TYPES (type); if (TREE_CODE (type) == METHOD_TYPE) { type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types)); arg_types = TREE_CHAIN (arg_types); } if (TREE_TYPE (type) != void_type_node) e1 = 1, error ("`operator delete' must return type `void'"); if (arg_types == NULL_TREE || TREE_VALUE (arg_types) != ptr_type_node) e2 = 1, error ("`operator delete' takes type `void *' as first parameter"); if (arg_types && TREE_CHAIN (arg_types) && TREE_CHAIN (arg_types) != void_list_node) { /* Again, technically this argument must be `size_t', but again we may not know what that is. */ tree t2 = TREE_VALUE (TREE_CHAIN (arg_types)); if (TREE_CODE (t2) != INTEGER_TYPE || TYPE_PRECISION (t2) != TYPE_PRECISION (sizetype)) e3 = 1, error ("second argument to `operator delete' must be of type `size_t'"); else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node) { e3 = 1; if (TREE_CHAIN (TREE_CHAIN (arg_types))) error ("too many arguments in declaration of `operator delete'"); else error ("`...' invalid in specification of `operator delete'"); } } if (e3) arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype)); else if (e3 |= e2) { if (arg_types == NULL_TREE) arg_types = void_list_node; else arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); } else e3 |= e1; if (e3) type = build_function_type (void_type_node, arg_types); return type;}static voidwrite_vtable_entries (decl) tree decl;{ tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl))); if (flag_dossier) entries = TREE_CHAIN (entries); for (; entries; entries = TREE_CHAIN (entries)) { tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); tree fn = TREE_OPERAND (fnaddr, 0); if (! DECL_EXTERNAL (fn) && ! TREE_ASM_WRITTEN (fn) && DECL_SAVED_INSNS (fn)) { if (TREE_PUBLIC (DECL_CLASS_CONTEXT (fn))) TREE_PUBLIC (fn) = 1; TREE_ADDRESSABLE (fn) = 1; output_inline_function (fn); } else assemble_external (fn); }}static voidfinish_vtable_typedecl (prev, vars) tree prev, vars;{ tree decl = TYPE_BINFO_VTABLE (TREE_TYPE (vars)); /* If we are controlled by `+e2', obey. */ if (write_virtuals == 2) { tree binfo = value_member (DECL_NAME (vars), pending_vtables); if (binfo) TREE_PURPOSE (binfo) = void_type_node; else decl = NULL_TREE; } /* If this type has inline virtual functions, then write those functions out now. */ if (decl && write_virtuals >= 0 && ! DECL_EXTERNAL (decl) && (TREE_PUBLIC (decl) || TREE_USED (decl))) write_vtable_entries (decl);}static voidfinish_vtable_vardecl (prev, vars) tree prev, vars;{ if (write_virtuals >= 0 && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))) { extern tree the_null_vtable_entry; /* Stuff this virtual function table's size into `pfn' slot of `the_null_vtable_entry'. */ tree nelts = array_type_nelts (TREE_TYPE (vars)); SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts); /* Kick out the dossier before writing out the vtable. */ if (flag_dossier) rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1); /* Write it out. */ write_vtable_entries (vars); if (TREE_TYPE (DECL_INITIAL (vars)) == 0) store_init_value (vars, DECL_INITIAL (vars)); rest_of_decl_compilation (vars, 0, 1, 1); } /* We know that PREV must be non-zero here. */ TREE_CHAIN (prev) = TREE_CHAIN (vars);}voidwalk_vtables (typedecl_fn, vardecl_fn) register void (*typedecl_fn)(); register void (*vardecl_fn)();{ tree prev, vars; for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars)) { if (TREE_CODE (vars) == TYPE_DECL && TYPE_LANG_SPECIFIC (TREE_TYPE (vars)) && CLASSTYPE_VSIZE (TREE_TYPE (vars))) { if (typedecl_fn) (*typedecl_fn) (prev, vars); } else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) { if (vardecl_fn) (*vardecl_fn) (prev, vars); } else prev = vars; }}extern int parse_time, varconst_time;#define TIMEVAR(VAR, BODY) \do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)/* This routine is called from the last rule in yyparse (). Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction first, since that way we only need to reverse the decls once. */voidfinish_file (){ extern int lineno; int start_time, this_time; char *buf; char *p; tree fnname; tree vars = static_aggregates; int needs_cleaning = 0, needs_messing_up = 0; if (main_input_filename == 0) main_input_filename = input_filename; if (!first_global_object_name) first_global_object_name = main_input_filename; buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (first_global_object_name)); if (flag_detailed_statistics) dump_tree_statistics (); /* Bad parse errors. Just forget about it. */ if (! global_bindings_p () || current_class_type) return; start_time = get_run_time (); /* Push into C language context, because that's all we'll need here. */ push_lang_context (lang_name_c); /* Set up the name of the file-level functions we may need. */ /* Use a global object (which is already required to be unique over the program) rather than the file name (which imposes extra constraints). -- Raeburn@MIT.EDU, 10 Jan 1990. */ sprintf (buf, FILE_FUNCTION_FORMAT, first_global_object_name); /* Don't need to pull wierd characters out of global names. */ if (first_global_object_name == main_input_filename) { for (p = buf+11; *p; p++) if (! ((*p >= '0' && *p <= '9')#if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */#ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */ || *p == '.'#endif#endif#ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */ || *p == '$'#endif || (*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))) *p = '_'; } /* See if we really need the hassle. */ while (vars && needs_cleaning == 0) { tree decl = TREE_VALUE (vars); tree type = TREE_TYPE (decl); if (TYPE_NEEDS_DESTRUCTOR (type)) { needs_cleaning = 1; needs_messing_up = 1; break; } else needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type); vars = TREE_CHAIN (vars); } if (needs_cleaning == 0) goto mess_up; /* Otherwise, GDB can get confused, because in only knows about source for LINENO-1 lines. */ lineno -= 1; fnname = get_identifier (buf); start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); fnname = DECL_ASSEMBLER_NAME (current_function_decl); store_parm_decls (); pushlevel (0); clear_last_expr (); push_momentary (); expand_start_bindings (0); /* These must be done in backward order to destroy, in which they happen to be! */ while (vars) { tree decl = TREE_VALUE (vars); tree type = TREE_TYPE (decl); tree temp = TREE_PURPOSE (vars); if (TYPE_NEEDS_DESTRUCTOR (type)) { if (TREE_STATIC (vars)) expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node), 0); if (TREE_CODE (type) == ARRAY_TYPE) temp = decl; else { mark_addressable (decl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -