/* Search in the interfaces of SEARCHED_CLASS and its superinterfaces for a method matching METHOD_NAME and signature SIGNATURE. A private helper for lookup_do. */ static tree find_method_in_interfaces (tree searched_class, int flags, tree method_name, tree signature, tree (*signature_builder) (tree)) { int i; tree binfo, base_binfo; for (binfo = TYPE_BINFO (searched_class), i = 1; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree iclass = BINFO_TYPE (base_binfo); tree method; /* If the superinterface hasn't been loaded yet, do so now. */ if (!CLASS_LOADED_P (iclass)) load_class (iclass, 1); /* First, we look in ICLASS. If that doesn't work we'll recursively look through all its superinterfaces. */ method = shallow_find_method (iclass, flags, method_name, signature, signature_builder); if (method != NULL_TREE) return method; method = find_method_in_interfaces (iclass, flags, method_name, signature, signature_builder); if (method != NULL_TREE) return method; } return NULL_TREE; }
static void record_target_from_binfo (vec <cgraph_node *> &nodes, tree binfo, tree otr_type, tree type_binfo, HOST_WIDE_INT otr_token, tree outer_type, HOST_WIDE_INT offset, pointer_set_t *inserted, pointer_set_t *matched_vtables, bool anonymous) { tree type = BINFO_TYPE (binfo); int i; tree base_binfo; gcc_checking_assert (BINFO_VTABLE (type_binfo)); if (types_same_for_odr (type, outer_type)) { tree inner_binfo = get_binfo_at_offset (type_binfo, offset, otr_type); /* For types in anonymous namespace first check if the respective vtable is alive. If not, we know the type can't be called. */ if (!flag_ltrans && anonymous) { tree vtable = BINFO_VTABLE (inner_binfo); struct varpool_node *vnode; if (TREE_CODE (vtable) == POINTER_PLUS_EXPR) vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0); vnode = varpool_get_node (vtable); if (!vnode || !vnode->definition) return; } gcc_assert (inner_binfo); if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo))) { tree target = gimple_get_virt_method_for_binfo (otr_token, inner_binfo); if (target) maybe_record_node (nodes, target, inserted, NULL); } return; } /* Walk bases. */ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) /* Walking bases that have no virtual method is pointless excercise. */ if (polymorphic_type_binfo_p (base_binfo)) record_target_from_binfo (nodes, base_binfo, otr_type, /* In the case of single inheritance, the virtual table is shared with the outer type. */ BINFO_VTABLE (base_binfo) ? base_binfo : type_binfo, otr_token, outer_type, offset, inserted, matched_vtables, anonymous); }
static tree synthesize_exception_spec (tree type, tree (*extractor) (tree, void*), void *client) { tree raises = empty_except_spec; tree fields = TYPE_FIELDS (type); tree binfo, base_binfo; int i; for (binfo = TYPE_BINFO (type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree fn = (*extractor) (BINFO_TYPE (base_binfo), client); if (fn) { tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); raises = merge_exception_specifiers (raises, fn_raises); } } for (; fields; fields = TREE_CHAIN (fields)) { tree type = TREE_TYPE (fields); tree fn; if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) continue; while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); if (!CLASS_TYPE_P (type)) continue; fn = (*extractor) (type, client); if (fn) { tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); raises = merge_exception_specifiers (raises, fn_raises); } } return raises; }
static void dequeue_and_dump (dump_info_p di) { dump_queue_p dq; splay_tree_node stn; dump_node_info_p dni; tree t; unsigned int index; enum tree_code code; enum tree_code_class code_class; const char* code_name; /* Get the next node from the queue. */ dq = di->queue; stn = dq->node; t = (tree) stn->key; dni = (dump_node_info_p) stn->value; index = dni->index; /* Remove the node from the queue, and put it on the free list. */ di->queue = dq->next; if (!di->queue) di->queue_end = 0; dq->next = di->free_list; di->free_list = dq; /* Print the node index. */ dump_index (di, index); /* And the type of node this is. */ if (dni->binfo_p) code_name = "binfo"; else code_name = tree_code_name[(int) TREE_CODE (t)]; fprintf (di->stream, "%-16s ", code_name); di->column = 25; /* Figure out what kind of node this is. */ code = TREE_CODE (t); code_class = TREE_CODE_CLASS (code); /* Although BINFOs are TREE_VECs, we dump them specially so as to be more informative. */ if (dni->binfo_p) { unsigned ix; tree base; VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t); dump_child ("type", BINFO_TYPE (t)); if (BINFO_VIRTUAL_P (t)) dump_string_field (di, "spec", "virt"); dump_int (di, "bases", BINFO_N_BASE_BINFOS (t)); for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++) { tree access = (accesses ? VEC_index (tree, accesses, ix) : access_public_node); const char *string = NULL; if (access == access_public_node) string = "pub"; else if (access == access_protected_node) string = "prot"; else if (access == access_private_node) string = "priv"; else gcc_unreachable (); dump_string_field (di, "accs", string); queue_and_dump_index (di, "binf", base, DUMP_BINFO); } goto done; } /* We can knock off a bunch of expression nodes in exactly the same way. */ if (IS_EXPR_CODE_CLASS (code_class)) { /* If we're dumping children, dump them now. */ queue_and_dump_type (di, t); switch (code_class) { case tcc_unary: dump_child ("op 0", TREE_OPERAND (t, 0)); break; case tcc_binary: case tcc_comparison: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case tcc_expression: case tcc_reference: case tcc_statement: case tcc_vl_exp: /* These nodes are handled explicitly below. */ break; default: gcc_unreachable (); } } else if (DECL_P (t)) { expanded_location xloc; /* All declarations have names. */ if (DECL_NAME (t)) dump_child ("name", DECL_NAME (t)); if (DECL_ASSEMBLER_NAME_SET_P (t) && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t)) dump_child ("mngl", DECL_ASSEMBLER_NAME (t)); if (DECL_ABSTRACT_ORIGIN (t)) dump_child ("orig", DECL_ABSTRACT_ORIGIN (t)); /* And types. */ queue_and_dump_type (di, t); dump_child ("scpe", DECL_CONTEXT (t)); /* And a source position. */ xloc = expand_location (DECL_SOURCE_LOCATION (t)); if (xloc.file) { const char *filename = lbasename (xloc.file); dump_maybe_newline (di); fprintf (di->stream, "srcp: %s:%-6d ", filename, xloc.line); di->column += 6 + strlen (filename) + 8; } /* And any declaration can be compiler-generated. */ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON) && DECL_ARTIFICIAL (t)) dump_string_field (di, "note", "artificial"); if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL)) dump_child ("chain", DECL_CHAIN (t)); } else if (code_class == tcc_type) { /* All types have qualifiers. */ int quals = lang_hooks.tree_dump.type_quals (t); if (quals != TYPE_UNQUALIFIED) { fprintf (di->stream, "qual: %c%c%c ", (quals & TYPE_QUAL_CONST) ? 'c' : ' ', (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ', (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' '); di->column += 14; } /* All types have associated declarations. */ dump_child ("name", TYPE_NAME (t)); /* All types have a main variant. */ if (TYPE_MAIN_VARIANT (t) != t) dump_child ("unql", TYPE_MAIN_VARIANT (t)); /* And sizes. */ dump_child ("size", TYPE_SIZE (t)); /* All types have alignments. */ dump_int (di, "algn", TYPE_ALIGN (t)); } else if (code_class == tcc_constant) /* All constants can have types. */ queue_and_dump_type (di, t); /* Give the language-specific code a chance to print something. If it's completely taken care of things, don't bother printing anything more ourselves. */ if (lang_hooks.tree_dump.dump_tree (di, t)) goto done; /* Now handle the various kinds of nodes. */ switch (code) { int i; case IDENTIFIER_NODE: dump_string_field (di, "strg", IDENTIFIER_POINTER (t)); dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); break; case TREE_LIST: dump_child ("purp", TREE_PURPOSE (t)); dump_child ("valu", TREE_VALUE (t)); dump_child ("chan", TREE_CHAIN (t)); break; case STATEMENT_LIST: { tree_stmt_iterator it; for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, tsi_stmt (it)); } } break; case TREE_VEC: dump_int (di, "lngt", TREE_VEC_LENGTH (t)); for (i = 0; i < TREE_VEC_LENGTH (t); ++i) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, TREE_VEC_ELT (t, i)); } break; case INTEGER_TYPE: case ENUMERAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_child ("min", TYPE_MIN_VALUE (t)); dump_child ("max", TYPE_MAX_VALUE (t)); if (code == ENUMERAL_TYPE) dump_child ("csts", TYPE_VALUES (t)); break; case REAL_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); break; case FIXED_POINT_TYPE: dump_int (di, "prec", TYPE_PRECISION (t)); dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed"); dump_string_field (di, "saturating", TYPE_SATURATING (t) ? "saturating": "non-saturating"); break; case POINTER_TYPE: dump_child ("ptd", TREE_TYPE (t)); break; case REFERENCE_TYPE: dump_child ("refd", TREE_TYPE (t)); break; case METHOD_TYPE: dump_child ("clas", TYPE_METHOD_BASETYPE (t)); /* Fall through. */ case FUNCTION_TYPE: dump_child ("retn", TREE_TYPE (t)); dump_child ("prms", TYPE_ARG_TYPES (t)); break; case ARRAY_TYPE: dump_child ("elts", TREE_TYPE (t)); dump_child ("domn", TYPE_DOMAIN (t)); break; case RECORD_TYPE: case UNION_TYPE: if (TREE_CODE (t) == RECORD_TYPE) dump_string_field (di, "tag", "struct"); else dump_string_field (di, "tag", "union"); dump_child ("flds", TYPE_FIELDS (t)); dump_child ("fncs", TYPE_METHODS (t)); queue_and_dump_index (di, "binf", TYPE_BINFO (t), DUMP_BINFO); break; case CONST_DECL: dump_child ("cnst", DECL_INITIAL (t)); break; case DEBUG_EXPR_DECL: dump_int (di, "-uid", DEBUG_TEMP_UID (t)); /* Fall through. */ case VAR_DECL: case PARM_DECL: case FIELD_DECL: case RESULT_DECL: if (TREE_CODE (t) == PARM_DECL) dump_child ("argt", DECL_ARG_TYPE (t)); else dump_child ("init", DECL_INITIAL (t)); dump_child ("size", DECL_SIZE (t)); dump_int (di, "algn", DECL_ALIGN (t)); if (TREE_CODE (t) == FIELD_DECL) { if (DECL_FIELD_OFFSET (t)) dump_child ("bpos", bit_position (t)); } else if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) { dump_int (di, "used", TREE_USED (t)); if (DECL_REGISTER (t)) dump_string_field (di, "spec", "register"); } break; case FUNCTION_DECL: dump_child ("args", DECL_ARGUMENTS (t)); if (DECL_EXTERNAL (t)) dump_string_field (di, "body", "undefined"); if (TREE_PUBLIC (t)) dump_string_field (di, "link", "extern"); else dump_string_field (di, "link", "static"); if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t)) dump_child ("body", DECL_SAVED_TREE (t)); break; case INTEGER_CST: if (TREE_INT_CST_HIGH (t)) dump_int (di, "high", TREE_INT_CST_HIGH (t)); dump_int (di, "low", TREE_INT_CST_LOW (t)); break; case STRING_CST: fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t)); dump_int (di, "lngt", TREE_STRING_LENGTH (t)); break; case REAL_CST: dump_real (di, "valu", TREE_REAL_CST_PTR (t)); break; case FIXED_CST: dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t)); break; case TRUTH_NOT_EXPR: case ADDR_EXPR: case INDIRECT_REF: case CLEANUP_POINT_EXPR: case SAVE_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: /* These nodes are unary, but do not have code class `1'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); break; case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: case INIT_EXPR: case MODIFY_EXPR: case COMPOUND_EXPR: case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: case POSTDECREMENT_EXPR: case POSTINCREMENT_EXPR: /* These nodes are binary, but do not have code class `2'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case COMPONENT_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case ARRAY_REF: case ARRAY_RANGE_REF: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); dump_child ("op 3", TREE_OPERAND (t, 3)); break; case COND_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); dump_child ("op 2", TREE_OPERAND (t, 2)); break; case TRY_FINALLY_EXPR: dump_child ("op 0", TREE_OPERAND (t, 0)); dump_child ("op 1", TREE_OPERAND (t, 1)); break; case CALL_EXPR: { int i = 0; tree arg; call_expr_arg_iterator iter; dump_child ("fn", CALL_EXPR_FN (t)); FOR_EACH_CALL_EXPR_ARG (arg, iter, t) { char buffer[32]; sprintf (buffer, "%u", i); dump_child (buffer, arg); i++; } } break; case CONSTRUCTOR: { unsigned HOST_WIDE_INT cnt; tree index, value; dump_int (di, "lngt", VEC_length (constructor_elt, CONSTRUCTOR_ELTS (t))); FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value) { dump_child ("idx", index); dump_child ("val", value); } }
static void sdbout_one_type (tree type) { if (current_function_decl != NULL_TREE && DECL_SECTION_NAME (current_function_decl) != NULL_TREE) ; /* Don't change section amid function. */ else switch_to_section (text_section); switch (TREE_CODE (type)) { case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: case ENUMERAL_TYPE: type = TYPE_MAIN_VARIANT (type); /* Don't output a type twice. */ if (TREE_ASM_WRITTEN (type)) /* James said test TREE_ASM_BEING_WRITTEN here. */ return; /* Output nothing if type is not yet defined. */ if (!COMPLETE_TYPE_P (type)) return; TREE_ASM_WRITTEN (type) = 1; /* This is reputed to cause trouble with the following case, but perhaps checking TYPE_SIZE above will fix it. */ /* Here is a testcase: struct foo { struct badstr *bbb; } forwardref; typedef struct intermediate { int aaaa; } intermediate_ref; typedef struct badstr { int ccccc; } badtype; */ /* This change, which ought to make better output, used to make the COFF assembler unhappy. Changes involving KNOWN_TYPE_TAG may fix the problem. */ /* Before really doing anything, output types we want to refer to. */ /* Note that in version 1 the following two lines are not used if forward references are in use. */ if (TREE_CODE (type) != ENUMERAL_TYPE) sdbout_field_types (type); /* Output a structure type. */ { int size = int_size_in_bytes (type); int member_scl = 0; tree tem; /* Record the type tag, but not in its permanent place just yet. */ sdbout_record_type_name (type); PUT_SDB_DEF (KNOWN_TYPE_TAG (type)); switch (TREE_CODE (type)) { case UNION_TYPE: case QUAL_UNION_TYPE: PUT_SDB_SCL (C_UNTAG); PUT_SDB_TYPE (T_UNION); member_scl = C_MOU; break; case RECORD_TYPE: PUT_SDB_SCL (C_STRTAG); PUT_SDB_TYPE (T_STRUCT); member_scl = C_MOS; break; case ENUMERAL_TYPE: PUT_SDB_SCL (C_ENTAG); PUT_SDB_TYPE (T_ENUM); member_scl = C_MOE; break; default: break; } PUT_SDB_SIZE (size); PUT_SDB_ENDEF; /* Print out the base class information with fields named after the types they hold. */ /* This is only relevant to aggregate types. TYPE_BINFO is used for other purposes in an ENUMERAL_TYPE, so we must exclude that case. */ if (TREE_CODE (type) != ENUMERAL_TYPE && TYPE_BINFO (type)) { int i; tree binfo, child; for (binfo = TYPE_BINFO (type), i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++) { tree child_type = BINFO_TYPE (child); tree child_type_name; if (TYPE_NAME (child_type) == 0) continue; if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE) child_type_name = TYPE_NAME (child_type); else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL) { child_type_name = DECL_NAME (TYPE_NAME (child_type)); if (child_type_name && template_name_p (child_type_name)) child_type_name = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type)); } else continue; PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name)); PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0)); PUT_SDB_SCL (member_scl); sdbout_type (BINFO_TYPE (child)); PUT_SDB_ENDEF; } } /* Output the individual fields. */ if (TREE_CODE (type) == ENUMERAL_TYPE) { for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { tree value = TREE_VALUE (tem); if (TREE_CODE (value) == CONST_DECL) value = DECL_INITIAL (value); if (host_integerp (value, 0)) { PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem))); PUT_SDB_INT_VAL (tree_low_cst (value, 0)); PUT_SDB_SCL (C_MOE); PUT_SDB_TYPE (T_MOE); PUT_SDB_ENDEF; } } } else /* record or union type */ for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) /* Output the name, type, position (in bits), size (in bits) of each field. */ /* Omit here the nameless fields that are used to skip bits. Also omit fields with variable size or position. Also omit non FIELD_DECL nodes that GNU C++ may put here. */ if (TREE_CODE (tem) == FIELD_DECL && DECL_NAME (tem) && DECL_SIZE (tem) && host_integerp (DECL_SIZE (tem), 1) && host_integerp (bit_position (tem), 0)) { const char *name; name = IDENTIFIER_POINTER (DECL_NAME (tem)); PUT_SDB_DEF (name); if (DECL_BIT_FIELD_TYPE (tem)) { PUT_SDB_INT_VAL (int_bit_position (tem)); PUT_SDB_SCL (C_FIELD); sdbout_type (DECL_BIT_FIELD_TYPE (tem)); PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1)); } else { PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT); PUT_SDB_SCL (member_scl); sdbout_type (TREE_TYPE (tem)); } PUT_SDB_ENDEF; } /* Output end of a structure,union, or enumeral definition. */ PUT_SDB_PLAIN_DEF ("eos"); PUT_SDB_INT_VAL (size); PUT_SDB_SCL (C_EOS); PUT_SDB_TAG (KNOWN_TYPE_TAG (type)); PUT_SDB_SIZE (size); PUT_SDB_ENDEF; break; } default: break; } }
bool cp_dump_tree (void* dump_info, tree t) { enum tree_code code; dump_info_p di = (dump_info_p) dump_info; /* Figure out what kind of node this is. */ code = TREE_CODE (t); if (DECL_P (t)) { if (DECL_LANG_SPECIFIC (t) && DECL_LANGUAGE (t) != lang_cplusplus) dump_string (di, language_to_string (DECL_LANGUAGE (t))); } switch (code) { case IDENTIFIER_NODE: if (IDENTIFIER_OPNAME_P (t)) { dump_string (di, "operator"); return true; } else if (IDENTIFIER_TYPENAME_P (t)) { dump_child ("tynm", TREE_TYPE (t)); return true; } break; case OFFSET_TYPE: dump_string (di, "ptrmem"); dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t)); dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); return true; case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) { dump_string (di, "ptrmem"); dump_child ("ptd", TYPE_PTRMEM_POINTED_TO_TYPE (t)); dump_child ("cls", TYPE_PTRMEM_CLASS_TYPE (t)); return true; } /* Fall through. */ case UNION_TYPE: /* Is it a type used as a base? */ if (TYPE_CONTEXT (t) && TREE_CODE (TYPE_CONTEXT (t)) == TREE_CODE (t) && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t) { dump_child ("bfld", TYPE_CONTEXT (t)); return true; } if (! IS_AGGR_TYPE (t)) break; dump_child ("vfld", TYPE_VFIELD (t)); if (CLASSTYPE_TEMPLATE_SPECIALIZATION(t)) dump_string(di, "spec"); if (!dump_flag (di, TDF_SLIM, t) && TYPE_BINFO (t)) { int i; tree binfo; tree base_binfo; for (binfo = TYPE_BINFO (t), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) { dump_child ("base", BINFO_TYPE (base_binfo)); if (BINFO_VIRTUAL_P (base_binfo)) dump_string (di, "virtual"); dump_access (di, base_binfo); } } break; case FIELD_DECL: dump_access (di, t); if (DECL_MUTABLE_P (t)) dump_string(di, "mutable"); break; case VAR_DECL: if (TREE_CODE (CP_DECL_CONTEXT (t)) == RECORD_TYPE) dump_access (di, t); if (TREE_STATIC (t) && !TREE_PUBLIC (t)) dump_string (di, "static"); break; case FUNCTION_DECL: if (!DECL_THUNK_P (t)) { if (DECL_OVERLOADED_OPERATOR_P (t)) { dump_string (di, "operator"); dump_op (di, t); } if (DECL_FUNCTION_MEMBER_P (t)) { dump_string (di, "member"); dump_access (di, t); } if (DECL_PURE_VIRTUAL_P (t)) dump_string (di, "pure"); if (DECL_VIRTUAL_P (t)) dump_string (di, "virtual"); if (DECL_CONSTRUCTOR_P (t)) dump_string (di, "constructor"); if (DECL_DESTRUCTOR_P (t)) dump_string (di, "destructor"); if (DECL_CONV_FN_P (t)) dump_string (di, "conversion"); if (DECL_GLOBAL_CTOR_P (t)) dump_string (di, "global init"); if (DECL_GLOBAL_DTOR_P (t)) dump_string (di, "global fini"); if (DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)) dump_string (di, "pseudo tmpl"); } else { tree virt = THUNK_VIRTUAL_OFFSET (t); dump_string (di, "thunk"); if (DECL_THIS_THUNK_P (t)) dump_string (di, "this adjusting"); else { dump_string (di, "result adjusting"); if (virt) virt = BINFO_VPTR_FIELD (virt); } dump_int (di, "fixd", THUNK_FIXED_OFFSET (t)); if (virt) dump_int (di, "virt", tree_low_cst (virt, 0)); dump_child ("fn", DECL_INITIAL (t)); } break; case NAMESPACE_DECL: if (DECL_NAMESPACE_ALIAS (t)) dump_child ("alis", DECL_NAMESPACE_ALIAS (t)); else if (!dump_flag (di, TDF_SLIM, t)) dump_child ("dcls", cp_namespace_decls (t)); break; case TEMPLATE_DECL: dump_child ("rslt", DECL_TEMPLATE_RESULT (t)); dump_child ("inst", DECL_TEMPLATE_INSTANTIATIONS (t)); dump_child ("spcs", DECL_TEMPLATE_SPECIALIZATIONS (t)); dump_child ("prms", DECL_TEMPLATE_PARMS (t)); break; case OVERLOAD: dump_child ("crnt", OVL_CURRENT (t)); dump_child ("chan", OVL_CHAIN (t)); break; case TRY_BLOCK: dump_stmt (di, t); if (CLEANUP_P (t)) dump_string (di, "cleanup"); dump_child ("body", TRY_STMTS (t)); dump_child ("hdlr", TRY_HANDLERS (t)); break; case EH_SPEC_BLOCK: dump_stmt (di, t); dump_child ("body", EH_SPEC_STMTS (t)); dump_child ("raises", EH_SPEC_RAISES (t)); break; case PTRMEM_CST: dump_child ("clas", PTRMEM_CST_CLASS (t)); dump_child ("mbr", PTRMEM_CST_MEMBER (t)); break; case THROW_EXPR: /* These nodes are unary, but do not have code class `1'. */ dump_child ("op 0", TREE_OPERAND (t, 0)); break; case AGGR_INIT_EXPR: dump_int (di, "ctor", AGGR_INIT_VIA_CTOR_P (t)); dump_child ("fn", TREE_OPERAND (t, 0)); dump_child ("args", TREE_OPERAND (t, 1)); dump_child ("decl", TREE_OPERAND (t, 2)); break; case HANDLER: dump_stmt (di, t); dump_child ("parm", HANDLER_PARMS (t)); dump_child ("body", HANDLER_BODY (t)); break; case MUST_NOT_THROW_EXPR: dump_stmt (di, t); dump_child ("body", TREE_OPERAND (t, 0)); break; case USING_STMT: dump_stmt (di, t); dump_child ("nmsp", USING_STMT_NAMESPACE (t)); break; case CLEANUP_STMT: dump_stmt (di, t); dump_child ("decl", CLEANUP_DECL (t)); dump_child ("expr", CLEANUP_EXPR (t)); dump_child ("body", CLEANUP_BODY (t)); break; case IF_STMT: dump_stmt (di, t); dump_child ("cond", IF_COND (t)); dump_child ("then", THEN_CLAUSE (t)); dump_child ("else", ELSE_CLAUSE (t)); break; default: break; } return c_dump_tree (di, t); }
static void do_build_assign_ref (tree fndecl) { tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree compound_stmt; compound_stmt = begin_compound_stmt (0); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) && is_empty_class (current_class_type)) /* Don't copy the padding byte; it might not have been allocated if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) { tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else { tree fields; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; tree binfo, base_binfo; /* Assign to each of the direct base classes. */ for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree converted_parm; /* We must convert PARM directly to the base class explicitly since the base class may be ambiguous. */ converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); /* Call the base class assignment operator. */ finish_expr_stmt (build_special_member_call (current_class_ref, ansi_assopname (NOP_EXPR), build_tree_list (NULL_TREE, converted_parm), base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); } /* Assign to each of the non-static data members. */ for (fields = TYPE_FIELDS (current_class_type); fields; fields = TREE_CHAIN (fields)) { tree comp = current_class_ref; tree init = parm; tree field = fields; tree expr_type; int quals; if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; expr_type = TREE_TYPE (field); if (CP_TYPE_CONST_P (expr_type)) { error ("non-static const member %q#D, can't use default " "assignment operator", field); continue; } else if (TREE_CODE (expr_type) == REFERENCE_TYPE) { error ("non-static reference member %q#D, can't use " "default assignment operator", field); continue; } if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type) != NULL_TREE) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE); /* Compute the type of init->field */ quals = cvquals; if (DECL_MUTABLE_P (field)) quals &= ~TYPE_QUAL_CONST; expr_type = cp_build_qualified_type (expr_type, quals); init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); if (DECL_NAME (field)) init = build_modify_expr (comp, NOP_EXPR, init); else init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); finish_expr_stmt (init); } } finish_return_stmt (current_class_ref); finish_compound_stmt (compound_stmt); }
static void do_build_copy_constructor (tree fndecl) { tree parm = FUNCTION_FIRST_USER_PARM (fndecl); parm = convert_from_reference (parm); if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type) && is_empty_class (current_class_type)) /* Don't copy the padding byte; it might not have been allocated if *this is a base subobject. */; else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) { tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); finish_expr_stmt (t); } else { tree fields = TYPE_FIELDS (current_class_type); tree member_init_list = NULL_TREE; int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; tree binfo, base_binfo; VEC(tree,gc) *vbases; /* Initialize all the base-classes with the parameter converted to their type so that we get their copy constructor and not another constructor that takes current_class_type. We must deal with the binfo's directly as a direct base might be inaccessible due to ambiguity. */ for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; VEC_iterate (tree, vbases, i, binfo); i++) { member_init_list = tree_cons (binfo, build_tree_list (NULL_TREE, build_base_path (PLUS_EXPR, parm, binfo, 1)), member_init_list); } for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { if (BINFO_VIRTUAL_P (base_binfo)) continue; member_init_list = tree_cons (base_binfo, build_tree_list (NULL_TREE, build_base_path (PLUS_EXPR, parm, base_binfo, 1)), member_init_list); } for (; fields; fields = TREE_CHAIN (fields)) { tree init = parm; tree field = fields; tree expr_type; if (TREE_CODE (field) != FIELD_DECL) continue; expr_type = TREE_TYPE (field); if (DECL_NAME (field)) { if (VFIELD_NAME_P (DECL_NAME (field))) continue; } else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type)) /* Just use the field; anonymous types can't have nontrivial copy ctors or assignment ops. */; else continue; /* Compute the type of "init->field". If the copy-constructor parameter is, for example, "const S&", and the type of the field is "T", then the type will usually be "const T". (There are no cv-qualified variants of reference types.) */ if (TREE_CODE (expr_type) != REFERENCE_TYPE) { int quals = cvquals; if (DECL_MUTABLE_P (field)) quals &= ~TYPE_QUAL_CONST; expr_type = cp_build_qualified_type (expr_type, quals); } init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); init = build_tree_list (NULL_TREE, init); member_init_list = tree_cons (field, init, member_init_list); } finish_mem_initializers (member_init_list); } }